以下文章来源于数据库架构之美 ,作者数据库架构之美

我们知道mysql没有hash join,也没有merge join,所以在连接的时候只有一种算法nest loop join,nl join使用驱动表的结果集作为外表到内表中查找每一条记录,如果有索引,就会走索引扫描,没有索引就会全表扫。

nl join并不能适用所有场景,例如两个表都是很大的表的等值连接,这种场景是hash join所擅长的,而且是生产环境中最常见的场景。mysql在这个时候就显得力不从心,所以在使用mysql时我们可能会制定如下规范:禁止使用大表连接。这也是mysql永远的痛。不过据说8.0版本已经将hash join作为一个需求纳入了,我们拭目以待吧。

相比起来,postgresql的优化器十分的强劲。支持了hash join、nest loop、sort merge join,扫描算法支持seq scan、index scan、index only scan,同时还支持堆内元组技术(HOT)。在postgresql11版本中还加入了并行扫描,亲测在两张大表(一张1.6亿一张256万数据,均无索引)做join结果集300多万,pg开启并行大概20s以内就跑出结果,强于其他数据库。

上面讨论了两表join的算法,下面看看多表join时mysql和pg是如何处理的。多表join其实涉及到一个问题:如何找到代价最小的最优路径。为什么会有这个问题呢?因为在多表连接时,每两个表之间连接具有一个代价值,优化器会根据代价估算调整不同表join的顺序,最后算出一个最优或者近似最优代价,使用这个代价生成执行计划,这样就涉及到图论中的最短路径问题,不同的连接顺序组合代表了图的遍历,最优代价其实就是求无源图的最短路径问题。我们知道两种主流的最短路径算法是迪杰斯特拉(Dijkstra)算法和弗洛伊德(floyd)算法,这两种算法也是动态规划中的经典算法。

在mysql中计算最优代价使用贪心算法,而pg使用的是动态规划。

Mysql:

Mysql连接使用贪心算法,下面这个图表明了贪心算法的过程:

贪心算法的前提是确定源点,算法思想也和名字很像,只找当前步骤的最优解,是一种深度优先的解法,算法复杂度是O(n²)找到后继续深入下一层,直至达到终点。比如上图从A到G,使用贪心算法的路径是A->B->D->G算法,代价是1+2+6=9,很明显这并不是最优解,最优解我们肉眼可以看出来是A->C->F->G,代价是2+3+1=6。所以我们看贪心算法并不是全局最优的,但是优点是算法复杂度低,mysql可能也是基于这种考虑而使用贪心算法,不想将时间都浪费在计算代价上了,因为如果关联的表特别多,那么代价的计算是指数级增长,所以贪心算法虽然不是最优解,但是在连接表的数量很大的情况下具有一定优势。

Postgresql:

再来看看pg使用的动态规划,动态规划解决的是无源最短路径问题,我们想象一下其实多表连接本身就是一个无源最短路径问题,只是mysql在进行连接的时候随机选了一个作为起点而已。

动态规划的思想是将问题分解为子问题,将问题递推为子问题进行解决。以floyd算法为例。算法使用邻接矩阵来表示每个点之间的距离,如果没有连线,则代表无穷大。比如下面这个图:

弗洛伊德算法使用矩阵记录节点直接距离,它的强大之处在于它经过若干次计算后得到任意两个节点直接的最短距离,是真正意义上的无源最短路径算法,但是它的算法复杂度也比较高,是O(n³)。下面介绍一下该算法,算法的核心思想是如果a[ij]>a[ik]+a[kj],那么a[ij]=a[ik]+a[kj],对于每两个节点ab之间的距离,如果存在第三个中间节点c使得acb的距离更短,那么ab的距离使用acb代替,并更新到矩阵。这样的遍历过程我们大致就理解了需要三层循环,里面的两层循环是对于ab、ac、ad...de总共(n-1)*(n-1)种选择(自己对自己的距离不用计算)计算每个中间节点(最外层循环)的距离是否更小。矩阵计算过程如下:

对于第一行,依次计算ab,ac,ad,ae的距离是否有第三个节点进行替换,对于ab计算发现,ab<ac+cb&&ab<ad+db&&ab<ae+eb,所以ab不用更新,同理ac也不用更新,对于ad,计算得到ab+bd=6,ac+cd=∞,ae+ed=∞,于是更新ad=6,同理计算更新ae=8;然后依次计算下面几行。全部遍历完,经历了三层循环,算法复杂度是O(n³)。pg使用该算法能够得到最优执行计划,但是在表的个数很多时计算代价所付出的代价也很大。

综上,mysql使用贪心算法只能得到局部最优执行计划,但是计算最优解所消耗的代价较小,而pg使用动态规划能够得到最优执行计划,但是计算最优解算法复杂度较高,代价较大。但是总体上mysql的优化器相比pg还是有很大差距,pg的优化器甚至引入了基因算法,有很多比较学术的考量,当得起学术派数据库的称号,也希望mysql能够越来越好吧。

活动预告


2019 数据技术嘉年华来啦!现场大咖云集,与你共畅数据的魅力。现在加入,尽享早鸟票价优惠:

MySQL和PostgreSQL在多表连接算法上的差异相关推荐

  1. MySQL表连接算法

    1. 前言 MySQL属于关系型数据库,我们建的表大多也都存在业务上的关联关系,同时我们又不可能将所有的数据都冗余一份,这不符合数据库的设计范式.因此,当我们需要把多张表的数据融合在一起的时候,就需要 ...

  2. MySQL的7种JOIN表连接结果集,你了解几个?搞懂仅需1张图

    目录 实践 第一种 第二种 第三种 第四种 第五种 第六种 第七种 大家好呀!我是爷爷的茶七里香,周末啦~开森~,今天突然想起曾经面试遇到的MySQL题目,记录下来方便查阅!!!  MySQL的7种表 ...

  3. MySQL笔记 07:多表连接查询

    1. 分类 1.1 按年代分类 sql92标准:仅支持内连接 sql99标准[推荐]:支持内连接 + 交叉连接 + 左/右外连接 1.2 按功能分类 内连接:等值连接,非等值连接,自连接 外连接:左外 ...

  4. mysql表连接算法_如何在MySQL中连接多个表

    我需要FULL OUTER JOIN多个表.我知道如何从 here开始加入两个表.但我有几个表,我不能将它们应用于它们.我怎样才能实现它? 我的SQL代码,如下: INSERT INTO table ...

  5. mysql的设计模式,设计模式 – 数据库表连接的最佳设计模式

    在 Model-Driven Design中,您的应用程序中有逻辑实体,这些实体可以映射到物理数据库中的多个表.当然,您需要运行更复杂的sql来获取完整的实体,而Model类则是实现这些关系的地方. ...

  6. mysql多表查询连接的种类_MySQL中基本的多表连接查询教程

    一.多表连接类型1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','  如: 由于其返回的结果为被连接的两个数据表的乘积,因此当有WHERE ...

  7. OceanBase SQL 执行计划解读(二)──── 表连接和子查询

    前文<OceanBase SQL 执行计划解读(一)>介绍了单表查询中基本的执行计划解读,本文主要介绍简单的表连接和子查询相关的执行计划. 本文假设你对常用的表连接算法已有了解,包括:嵌套 ...

  8. 浅析数据库多表连接:KaiwuDB 的分布式 join 计算

    Join 是 SQL 中的常用操作.在实际的数据库应用中,我们经常需要从多个数据表中读取数据,这时我们就可以使用 SQL 语句中的连接(join),在两个或多个数据表中查询数据. 常用 Join 算法 ...

  9. mysql装完后navicat无法连接_重装mysql后导致Navicat连接失败

    今天重装了mysql数据库,然后再使用navicat去连接数据库的时候,一直报错 1251 Client does not support authentication protocol reques ...

最新文章

  1. Add A Qdisk After configure RHCS
  2. 传统云主机存在哪些问题和弊端?
  3. 机器视觉:面阵相机的传感器类型及实际应用分析
  4. Secondary NameNode:它究竟有什么作用?(转自:http://blog.csdn.net/xh16319/article/details/31375197)
  5. RabbitMQ direct交换机
  6. java开发和python哪个好学_学编程,Python和Java哪个更好?
  7. SAP Hybris MVC里的M指什么
  8. 研究生开题报告需要注意的几点
  9. CentOS7配置samba共享文件系统
  10. Selenium的一些技巧与错误处理
  11. textedit实时显示位置_奉化“实时公交”来了!再也不用在多变的天气里等公交啦!...
  12. python构造icmp数据包_Python原始套接字未接收ICMP数据包
  13. easydarwin 安装_EasyDarwin流媒体服务器
  14. 计算机网络-自顶向下方法 第五章课后习题答案(第七版)
  15. Symbol 数据类型
  16. 关于Python常用的办公自动化技巧
  17. 源支付3.1版本全开源版+店员监控软件+手机监控APP源码
  18. VS2010如何添加MSCOMM控件
  19. 【Delphi】中使用消息Messages(五)Windows消息
  20. Windows Live Message (MSN) 登陆错误解决办法 -- windows live communications platform 遇到问题需要关闭

热门文章

  1. 适合初学者的安卓开源项目_开源周初学者
  2. es6 Class简介
  3. 十.激光SLAM框架学习之LeGO-LOAM框架---算法原理和改进、项目工程代码
  4. 视觉SLAM笔记(61) 单目稠密建图
  5. ufei pe安装linux,制作UEFI(64位)下的WinPE + Ubuntu + Acronis多启动U盘
  6. 开关电源怎么测试文波_开关电源纹波标准与规范测试说明
  7. kafka查看broker上主副本_kafka分区及副本在broker的分配
  8. python如何导入numpy简书_如何使用python3.x成功导入numpy?
  9. 一个高质量的程序应具备哪些条件?_有料!报考云南省考公务员,应具备哪些条件?...
  10. 如何安装python3.8.1_如何用源代码安装Python 3.8.1