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

本文记录 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 parseSqlElasticRequestBuilder requestBuilder = queryAction.explain();// join 查询if(requestBuilder instanceof JoinRequestBuilder){// join 算法选择。包括:HashJoinElasticExecutor、NestedLoopsElasticExecutor// 如果关联条件为等值(Condition.OPEAR.EQ),则使用 HashJoinElasticExecutorElasticJoinExecutor 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 * FROMsale_line_info uJOIN 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 取值数据,都可以减少计算陈本,提高性能。

参考

  • 如何在分布式数据库中实现 Hash Join
  • 一文详解MySQL——Join的使用优化 - 掘金

作者:京东物流 杨攀

来源:京东云开发者社区

分布式数据库 Join 查询设计与实现浅析 | 京东云技术团队相关推荐

  1. 主流关系型分布式数据库选型与设计实战

    一.数据库从集中式到分布式的演进 1.1.传统单机数据库 从狭义概念来讲,"数据库"就是OLTP场景的关系型单机数据库,诸如老牌的Oracle.DB2等商业数据库以及开源产品MyS ...

  2. OceanBase CTO杨传辉:下一代企业级分布式数据库的一体化设计

    本文 本文作者杨传辉,花名日照,现任 OceanBase CTO.团队创始成员.本文根据4月28日的直播<下一代分布式数据库一体化设计>内容整理. 大家好,我是杨传辉,上个月和大家讨论了分 ...

  3. JOIN US | 京东云技术精英招聘

    诚聘精英 JOIN US 乙亥农历新年刚刚结束,京东云开放一大波技术岗位, 期待志同道合的加入我们的大家庭. 招聘岗位 SaaS运维工程师 SaaS运维lead 大数据算法工程师 云技术布道师 大数据 ...

  4. 分布式数据库实战第一节 分布式数据库的前世今生

    开篇词 吃透分布式数据库,提升职场竞争力 你好,我是高洪涛,前华为云技术专家.前当当网系统架构师和 Oracle DBA,也是 Apache ShardingSphere PMC 成员.作为创始团队核 ...

  5. 数据库架构设计——分布式数据库设计

    摘要 现在互联网应用已经普及,数据量不断增大.对淘宝.美团.百度等互联网业务来说,传统单实例数据库很难支撑其性能和存储的要求,所以分布式架构得到了很大发展.一定要认识到数据库技术正在经历一场较大的变革 ...

  6. 浅析分布式数据库同步技术理论

    [摘 要]如何高效.安全地保持数据库之间数据同步是当前数据库技术研究热点问题.本文对于分布式数据库系统同步传输技术,通过数据库同步机制研究解决了多级数据库信息交换过程中上下级数据库数据不一致问题.  ...

  7. 五种知名的分布式数据库大PK

    在过去的十年间,分布式系统已遍布全球.它们跨区域地使用编排技术,实现了横跨多个云服务提供商及本地基础设施的混合云式部署,负载平衡,以及高可用性.在此基础上,数据库领域也在不断迭代与发展.近年来,业界大 ...

  8. 分布式数据库:如何正确选择分片键?

    过去十年见证了分布式数据库的崛起不仅通过本地集群来实现负载均衡,并提供高可用性,还具有数据中心内的机架感知等属性.专为云而设计的分布式数据库,可以跨越可用性区域,通过编排技术,支持公有云.私有云.混合 ...

  9. java数据库中间件实现,分布式数据库中间件DDM的实现原理

    随着数据量不断增大,传统的架构模式难以解决业务量不断增长所带来的问题,特别是在业务成线性.甚至指数级上升的情况.此时我们不得不通过水平扩展,把数据库放到不同服务器上来解决问题,也就是我们说的数据库中间 ...

最新文章

  1. 企业系统门户需要哪些模块_灵活用工平台SAAS系统有哪些功能模块
  2. theme editor android,谷歌宣布将于下月停用 Material Theme Editor
  3. python图例重复显示_matplotlib中的图例中有重复项?
  4. Fundebug是这样备份数据的
  5. 华为P40 Pro相机高清细节图曝光:潜望式长焦镜头抢眼
  6. pip下载安装与环境配置
  7. 用hudson配置持续集成CI服务器几个关键的配置
  8. Mac下启动AndroidStudio失败
  9. IOUtils快速进行内容复制与常用方法
  10. 压测工具ab的安装(mac环境)
  11. Revel模板引擎Template基本语法
  12. CA1704:标识符应正确拼写
  13. Bit-Z合约关于平仓的说明
  14. java 正则表达式验证
  15. 组原5_指令流水线影响因素和流水线分类
  16. ALCOA+CCEA原则(数据完整性标准)
  17. 百度谷歌搜索引擎常用搜索技巧
  18. 回溯法求解0-1背包问题
  19. 【多目标优化】1. 多目标优化的相关基本概念
  20. oracle数据库system01,system01坏块的问题

热门文章

  1. 设计模式系列:搞懂原型模式,你也会分身
  2. 第一次用python3爬虫图片_Python3编程实现网络图片爬虫
  3. GOROOT与GOPATH
  4. .net core部署Nginx集群
  5. git删除分支,提示无法删除,怎么处理 ?
  6. 【JS数组转逗号分割的字符串】
  7. 魔兽世界怀旧版本最新服务器,魔兽世界怀旧服:等到80版本,TBC也会分出来,就像永久60服务器...
  8. Oracle存储过程的几种调用方式
  9. 把vim打造成牛逼的C++ IDE
  10. JS实现接掉落块游戏