摘要:
最近在搞一个列存储引擎的包含内连接的嵌套外连接过慢的问题, 连接执行过慢的原因分析见此前的博客分析, 虽然逻辑很绕, 但是也不是无法分析.
更麻烦的问题在于修改查询计划, 让其能按照代价更小的方式正确的执行.
遇到的问题比我在修改查询计划前设想的更为棘手, 本文做下记录.
包含内连接的嵌套外连接执行过慢的问题原因分析:
- 最关键的问题出在内连接生成的中间结果的大小上
- 在mysql/sql层, 将内连接的条件全部上推, 导致内连接没有过滤条件,结果就是内连接的结果是R与S的叉乘
- 外连接U与(R和S的叉乘)做运算, 现在条件全部集中在外连接这一层, 连接的时间复杂度达到了惊人的 U 连接 (R叉乘S)
- 外连接的执行策略为散列连接, 对U做构建散列, 使用R叉乘S的结果集做探测集
- 虽然在逻辑理解上可以认为是对U做构建散列,但是这里的散列是一种连续地址的空间, 每次查找元素, 时间复杂度并不是槽位映射的O(1), 而是要从头遍历整个连续地址空间的O(n)
- 所以整个的包含内连接的嵌套外连接的执行时间复杂度可以这么理解
- 对外表U构建散列, 耗时为 M(U)
- 使用R叉乘S的结果集做探测集, 设散列探测单个元素的时间复杂度为O(1), 这里先忽略线性地址空间的O(n)的复杂度导致的问题复杂性的升级, 那么探测过程的耗时可以理解为 N(R*S)
- 总的耗时可以理解为 M(U) + N(R*S)
- 在执行的过程中, 最大的问题便是R*