分布式数据库 Join 查询设计与实现浅析

分布式,数据库,join,查询,设计,实现,浅析 · 浏览次数 : 292

小编点评

**MySQL 分库分表 Join 查询** 使用 MySQL 分库分表进行 Join 查询时,需要按照以下步骤进行操作: 1. **分发查询语句:**根据需要将原始 SQL 语句分发到多个 MySQL 实例节点上,每个节点负责执行对应的分片。 2. **组装结果:**在各个节点中收集数据,并将结果组装在一起,形成最终的结果集。 3. **合并结果:**将所有结果合并到一个最终结果集中,并将其返回给客户端。 **Elasticsearch Join 查询** 与 MySQL 分库分表 Join 相似的,使用 Elasticsearch 进行 Join 查询时,需要按照以下步骤进行操作: 1. **解析 SQL 语句:**将 SQL 语句解析成一个 Elasticsearch 查询请求,包括两部分:查询部分和结果部分。 2. **创建 join 查询:**根据查询条件,创建一个包含 Join 查询的查询请求。 3. **执行查询:**使用 Elasticsearch 的搜索引擎执行查询请求,并返回结果。 **Join 算法的选择** 当进行 Join 查询时,需要选择合适的算法来处理数据组织和查询逻辑。常见的 Join 算法包括: * **Hash Join:**使用 hash 算法对关联字段进行散列,并使用这些 hash 值进行查找。 * **Nested Loop Join:**使用两张表中的关联字段建立中间表,并进行两轮遍历来处理数据。 * **Merge Join:**使用中间表将两张表的所有记录合并在一起,并进行排序或聚合。 **中间件的优化** 在进行分布式数据库中的 Join 查询时,可以使用中间件来优化查询性能。中间件可以缓存中间结果,并提供索引等优化功能。 **技术选型的建议** * 在进行 Join 查询之前,应确认关联字段的正确性。 * 使用合适的索引来优化查询性能。 * 考虑使用中间件来提高查询效率。 * 在优化中间件时,应考虑性能和可扩展性之间的平衡。

正文

相对于单例数据库的查询操作,分布式数据查询会有很多技术难题。

本文记录 Mysql 分库分表 和 Elasticsearch Join 查询的实现思路,了解分布式场景数据处理的设计方案。
文章从常用的关系型数据库 MySQL 的分库分表Join 分析,再到非关系型 ElasticSearch 来分析 Join 实现策略。逐步深入Join 的实现机制。

①Mysql 分库分表 Join 查询场景

分库分表场景下,查询语句如何分发,数据如何组织。相较于NoSQL 数据库,Mysql 在SQL 规范的范围内,相对比较容易适配分布式场景。

基于 sharding-jdbc 中间件的方案,了解整个设计思路。

sharding-jdbc

  • sharding-jdbc 代理了原始的 datasource, 实现 jdbc 规范来完成分库分表的分发和组装,应用层无感知。
  • 执行流程:SQL解析 => 执行器优化 => SQL路由 => SQL改写 => SQL执行 => 结果归并 io.shardingsphere.core.executor.ExecutorEngine#execute
  • Join 语句的解析,决定了要分发 SQL 到哪些实例节点上。对应SQL路由。
  • SQL 改写就是要把原始(逻辑)表名,改为实际分片的表名。
  • 复杂情况下,Join 查询分发的最多执行的次数 = 数据库实例 × 表A分片数 × 表B分片数

Code Insight

示例代码工程:git@github.com:cluoHeadon/sharding-jdbc-demo.git

/**
 * 执行查询 SQL 切入点,从这里可以完整 debug 执行流程
 * @see ShardingPreparedStatement#execute()
 * @see ParsingSQLRouter#route(String, List, SQLStatement) Join 查询实际涉及哪些表,就是在路由规则里匹配得出来的。
 */
public boolean execute() throws SQLException {
    try {
        // 根据参数(决定分片)和具体的SQL 来匹配相关的实际 Table。
        Collection<PreparedStatementUnit> preparedStatementUnits = route();
        // 使用线程池,分发执行和结果归并。
        return new PreparedStatementExecutor(getConnection().getShardingContext().getExecutorEngine(), routeResult.getSqlStatement().getType(), preparedStatementUnits).execute();
    } finally {
        JDBCShardingRefreshHandler.build(routeResult, connection).execute();
        clearBatch();
    }
}

SQL 路由策略

启用 sql 打印,直观看到实际分发执行的 SQL

# 打印的代码,就是在上述route 得出 ExecutionUnits 后,打印的
sharding.jdbc.config.sharding.props.sql.show=true

sharding-jdbc 根据不同的SQL 语句,会有不同的路由策略。我们关注的 Join 查询,实际相关就是以下两种策略。

  • StandardRoutingEngine binding-tables 模式
  • ComplexRoutingEngine 最复杂的情况,笛卡尔组合关联关系
-- 参数不明,不能定位分片的情况
select * from order o inner join order_item oi on o.order_id = oi.order_id 

-- 路由结果
-- Actual SQL: db1 ::: select * from order_1 o inner join order_item_1 oi on o.order_id = oi.order_id 
-- Actual SQL: db1 ::: select * from order_1 o inner join order_item_0 oi on o.order_id = oi.order_id 
-- Actual SQL: db1 ::: select * from order_0 o inner join order_item_1 oi on o.order_id = oi.order_id 
-- Actual SQL: db1 ::: select * from order_0 o inner join order_item_0 oi on o.order_id = oi.order_id 
-- Actual SQL: db0 ::: select * from order_1 o inner join order_item_1 oi on o.order_id = oi.order_id 
-- Actual SQL: db0 ::: select * from order_1 o inner join order_item_0 oi on o.order_id = oi.order_id 
-- Actual SQL: db0 ::: select * from order_0 o inner join order_item_1 oi on o.order_id = oi.order_id 
-- Actual SQL: db0 ::: select * from order_0 o inner join order_item_0 oi on o.order_id = oi.order_id

②Elasticsearch Join 查询场景

首先,对于 NoSQL 数据库,要求 Join 查询,可以考虑是不是使用场景和用法有问题。

然后,不可避免的,有些场景需要这个功能。Join 查询的实现更贴近SQL 引擎。

基于 elasticsearch-sql 组件的方案,了解大概的实现思路。

elasticsearch-sql

  • 这是个elasticsearch 插件,通过提供http 服务实现类 SQL 查询的功能,高版本的elasticsearch 已经具备该功能⭐
  • 因为 elasticsearch 没有 Join 查询的特性,所以实现 SQL Join 功能,需要提供更加底层的功能,涉及到 Join 算法。

Code Insight

源码地址:git@github.com:NLPchina/elasticsearch-sql.git

/**
 * Execute the ActionRequest and returns the REST response using the channel.
 * @see ElasticDefaultRestExecutor#execute
 * @see ESJoinQueryActionFactory#createJoinAction Join 算法选择
 */
@Override
public void execute(Client client, Map<String, String> params, QueryAction queryAction, RestChannel channel) throws Exception{
    // sql parse
    SqlElasticRequestBuilder requestBuilder = queryAction.explain();

    // join 查询
    if(requestBuilder instanceof JoinRequestBuilder){
        // join 算法选择。包括:HashJoinElasticExecutor、NestedLoopsElasticExecutor
        // 如果关联条件为等值(Condition.OPEAR.EQ),则使用 HashJoinElasticExecutor
        ElasticJoinExecutor executor = ElasticJoinExecutor.createJoinExecutor(client,requestBuilder);
        executor.run();
        executor.sendResponse(channel);
    }
    // 其他类型查询 ...
}

③More Than Join

Join 算法

  • 常用三种 Join 算法:Nested Loop Join,Hash Join、 Merge Join
  • MySQL 只支持 NLJ 或其变种,8.0.18 版本后支持 Hash Join
  • NLJ 相当于两个嵌套循环,用第一张表做 Outter Loop,第二张表做 Inner Loop,Outter Loop 的每一条记录跟 Inner Loop 的记录作比较,最终符合条件的就将该数据记录。
  • Hash Join 分为两个阶段; build 构建阶段和 probe 探测阶段。
  • 可以使用Explain 查看 MySQL 使用哪种 Join 算法。 需要的语法关键字: FORMAT=JSON or FORMAT=Tree
EXPLAIN FORMAT=JSON  
SELECT * FROM
    sale_line_info u
    JOIN sale_line_manager o ON u.sale_line_code = o.sale_line_code;
{
    "query_block": {
        "select_id": 1,
        // 使用的join 算法: nested_loop
        "nested_loop": [
            // 涉及join 的表以及对应的 key,其他的信息与常用explain 类似
            {
                "table": {
                    "table_name": "o",
                    "access_type": "ALL"
                }
            },
            {
                "table": {
                    "table_name": "u",
                    "access_type": "ref"
                }
            }
        ]
    }
}

Elasticsearch Nested类型

分析Elasticsearch 业务数据以及使用场景,还有一种选择是直接存储关联信息的文档。在 Elasticsearch 中,是以完整文档形式提供查询和检索,彻底避开使用 Join 相关的技术。

这样就牵扯到关联是归属类型的数据还是公用类型的数据、关联数据量的大小、关联数据的更新频率等。这些都是使用 Nested 类型需要考虑的因素。

更多的使用方法,可以从网上和官网找到,不做赘述。
我们现在有个业务功能正好使用到 Nested类型, 在查询和优化过程中,解决了非常大的难题。

总结

通过运行原理分析,对于运行流程有了清晰和深入的认知。

对于中间件的优化和技术选型更加有目的性,使用上会更加谨慎和小心。

明确的筛选条件,更小的筛选范围,limit 取值数据,都可以减少计算陈本,提高性能。

参考

作者:京东物流 杨攀

来源:京东云开发者社区

与分布式数据库 Join 查询设计与实现浅析相似的内容:

分布式数据库 Join 查询设计与实现浅析

本文记录 Mysql 分库分表 和 Elasticsearch Join 查询的实现思路,了解分布式场景数据处理的设计方案。文章从常用的关系型数据库 MySQL 的分库分表Join 分析,再到非关系型 ElasticSearch 来分析 Join 实现策略。逐步深入Join 的实现机制。

SQL调优

**1. 索引优化:** 确保适当的索引在数据库表上创建,以加快查询性能。分析查询语句,确定可能需要的列和联合索引,并避免过多或不必要的索引。 **2. 优化查询语句:** 优化查询语句的写法,避免**全表扫描**和不必要的数据检索。使用合适的WHERE子句、JOIN语句和子查询,以提高查询效率。

在线问诊 Python、FastAPI、Neo4j — 构建问题分类器

目录构建字典数据构建 Trie 字典树按实体组装字典问题分析 将问题进行分析,和系统已有的分类进行关联 构建字典数据 将构建的知识图片字典化, 用于后面对问题的解析,下图为症状的字典,其它字典同理 构建 Trie 字典树 将建字典数据,组装集合 cur_dir = '/'.join(os.path.

[转帖]分布式数据库中间件:MyCat 和 ShardingSphere 对比说明

2022-05-29 16:537540转载MySQL 原文链接:https://blog.csdn.net/horses/article/details/106086208 本文转载自 https://blog.csdn.net/horses/article/details/106086208 今

分布式数据库架构路线大揭秘

摘要:这些年大家都在谈分布式数据库,各大企业也纷纷开始做数据库的分布式改造。那么所谓的分布式数据库是什么?采用什么架构,优势在哪?为什么越来越多企业选择它?我们不妨一起来深入了解下。 本文分享自华为云社区《GaussDB分布式架构大揭秘》,作者:华为云数据库首席架构师 冯柯。 这些年大家都在谈分布式

华为云GaussDB以技术创新引领金融行业分布式转型

摘要:分布式数据库以大集群规模、弹性伸缩等优异特性,满足了银行业务发展的多种需求,也因此成为各大银行关键基础设施技术创新建设的首选。 今天,由北京先进数通与华为联合主办的“银行业数字化转型实践交流会“第二站在成都顺利进行,各行业专家在现场一起交流了金融行业数字化转型的技术创新和实践成果。华为中国HC

华为云数据库首席专家谈分布式数据应用挑战和发展建议

摘要:本文分析了分布式数据库发展情况、分布式数据库应用的主要问题,从行业应用的角度给出了分布式数据库发展的建议。 本文分享自华为云社区《数字化转型下我国分布式数据库应用挑战及发展建议》,作者:数据库领域科学家、华为云数据库GaussDB首席专家 冯柯。 当前,金融等重点行业都在进行数字化转型,而分布

[转帖]三款典型国产分布式数据库的对比评测

https://developer.aliyun.com/article/790151?utm_content=m_1000295370 简介: 编者按:近几年国产数据库市场风生水起,涌现了多款优秀的国产数据库产品,本文选取了三款典型的国产分布式数据库进行全方位对比压测,呈现了国产分布式数据库的发展

华为云GaussDB数据库荣获国际CC EAL4+级别认证

摘要:近日,华为云GaussDB企业级分布式数据库内核正式通过了全球知名独立认证机构欧洲SGS Brightsight实验室的安全评估,获得全球权威信息技术安全性评估标准CC EAL4+级别认证。 本文分享自华为云社区《中国首个,我们拿下了!业界最高级别!华为云GaussDB数据库荣获国际CC EA

华为云新一代分布式数据库GaussDB,给世界一个更优选择

摘要:与伙伴一起,共建繁荣开放的GaussDB数据库新生态。 本文分享自华为云社区《华为云新一代分布式数据库GaussDB,给世界一个更优选择》,作者:华为云头条。 6月7日,在华为全球智慧金融峰会2023上,华为常务董事、华为云CEO张平安以“一切皆服务,做好金融数字化云底座和使能器”为主题发表演