StoneDB 子查询优化

StoneDB 子查询优化

摘要:

说明如何优化 exists 的 join 查询优化器的处理

核心函数:

TwoDimensionalJoiner::ChooseJoinAlgorithm

1JoinAlgType TwoDimensionalJoiner::ChooseJoinAlgorithm([[maybe_unused]] MultiIndex &mind, Condition &cond) { 2 JoinAlgType join_alg = JoinAlgType::JTYPE_GENERAL; 3 4 if (cond[0].IsType_JoinSimple() && cond[0].op == common::Operator::O_EQ) { 5 if ((cond.Size() == 1) && !stonedb_sysvar_force_hashjoin) 6 join_alg = JoinAlgType::JTYPE_MAP; // available types checked inside 7 else 8 join_alg = JoinAlgType::JTYPE_HASH; 9 } else { 10 if (cond[0].IsType_JoinSimple() && 11 (cond[0].op == common::Operator::O_MORE_EQ || cond[0].op == common::Operator::O_MORE || 12 cond[0].op == common::Operator::O_LESS_EQ || cond[0].op == common::Operator::O_LESS)) 13 join_alg = JoinAlgType::JTYPE_SORT; 14 } 15 return join_alg; 16}

选择 join 优化器问题分析:

  1. 仅判定 join simple 场景,未判断 exists 子句
  2. cond [0].IsType_JoinSimple () 如果走入了 else 分支,相当于被执行了两次

file

ChooseJoinAlgorithm 函数优化:

  1. 加入 exists 的判定,以 IsType_JoinSimple 和 == common::Operator::O_EQ 条件对待
  2. 优化代码结构,清理冗余的 cond [0].IsType_JoinSimple () 执行
  3. 其他逻辑不做任何修改
1JoinAlgType TwoDimensionalJoiner::ChooseJoinAlgorithm([[maybe_unused]] MultiIndex &mind, Condition &cond) { 2 do { 3 if (cond[0].IsExists()) { 4 break; 5 } 6 7 if (!cond[0].IsType_JoinSimple()) { 8 return JoinAlgType::JTYPE_GENERAL; 9 } 10 11 if (cond[0].op == common::Operator::O_EQ) { 12 break; 13 } 14 15 if (cond[0].op == common::Operator::O_MORE_EQ || cond[0].op == common::Operator::O_MORE || 16 cond[0].op == common::Operator::O_LESS_EQ || cond[0].op == common::Operator::O_LESS) { 17 return JoinAlgType::JTYPE_SORT; 18 } 19 } while (0); 20 21 JoinAlgType join_alg = JoinAlgType::JTYPE_HASH; 22 if ((!stonedb_sysvar_force_hashjoin) && (cond.Size() == 1)) 23 join_alg = JoinAlgType::JTYPE_MAP; // available types checked inside 24 25 return join_alg; 26}

代码优化后 exists 场景分析:

  1. 如果未开启强制 hash join 查询,且 cond.Size () == 1, 则进行 JTYPE_MAP 查询
  2. 需要强制开启 hash join 才可进入 hash join 查询,当前测试不开启强制的 hash join. 以 JTYPE_MAP 进行测试

优化走 JTYPE_MAP 查询测试:

MAP 子查询耗时:

1mysql> select 2-> o_orderpriority, 3-> count(*) as order_count 4-> from 5-> orders 6-> where 7-> o_orderdate >= date '1993-07-01' 8-> and o_orderdate < date '1993-07-01' + interval '3' month 9-> and exists ( 10 -> select 11 -> * 12 -> from 13 -> lineitem 14 -> where 15 -> l_orderkey = o_orderkey 16 -> and l_commitdate < l_receiptdate 17 -> ) 18 -> group by 19 -> o_orderpriority 20 -> order by 21 -> o_orderpriority ; 22 +-----------------+-------------+ 23 | o_orderpriority | order_count | 24 +-----------------+-------------+ 25 | 1-URGENT | 1147477 | 26 | 2-HIGH | 1146447 | 27 | 3-MEDIUM | 1146770 | 28 | 4-NOT SPECIFIED | 1146281 | 29 | 5-LOW | 1146801 | 30 +-----------------+-------------+ 31 5 rows in set (27.36 sec)

MAP 子查询对比之前的子查询耗时:

file

JTYPE_MAP 逻辑的火焰图

file

强制走 JTYPE_HASH 查询测试:

博主都是部署在cnaaa服务器上的,强制开启 hash join 优化,对比同样场景下与 map 查询的区别

HASH 子查询耗时:

1mysql> select 2 -> o_orderpriority, 3 -> count(*) as order_count 4 -> from 5 -> orders 6 -> where 7 -> o_orderdate >= date '1993-07-01' 8 -> and o_orderdate < date '1993-07-01' + interval '3' month 9 -> and exists ( 10 -> select 11 -> * 12 -> from 13 -> lineitem 14 -> where 15 -> l_orderkey = o_orderkey 16 -> and l_commitdate < l_receiptdate 17 -> ) 18 -> group by 19 -> o_orderpriority 20 -> order by 21 -> o_orderpriority ; 22+-----------------+-------------+ 23| o_orderpriority | order_count | 24+-----------------+-------------+ 25| 1-URGENT | 1147477 | 26| 2-HIGH | 1146447 | 27| 3-MEDIUM | 1146770 | 28| 4-NOT SPECIFIED | 1146281 | 29| 5-LOW | 1146801 | 30+-----------------+-------------+ 315 rows in set (27.60 sec)

HASH 子查询的火焰图:

file

点赞
收藏

评论区

加载中...

相关推荐

MySQL 子查询及其优化

使用过oracle或者其他关系数据库的DBA或者开发人员都有这样的经验,在子查询上都认为数据库已经做过优化,能够很好的选择驱动表执行,然后在把该经验移植到mysql数据库上,但是不幸的是,mysql在子查询的处理上有可能会让你大失所望,在我们的生产系统上就碰到过一些案例,例如:SELECTi_id,sum(i_sell)

MySQL总结(十一)子查询

!(https://oscimg.oschina.net/oscnet/upa344f41e81d3568e3310b5da00c57ced8ea.png)子查询1\.什么是子查询需求:查询开发部中有哪些员工selectfromemp;通

mysql5.6 分页查询优化

mysql5.6分页查询优化场景:表结构:主键(非自增)contentCode(varchar),过滤条件列为updateTime(timeStamp),已经为timestamp建立索引。搜索sql为:SELECTFROMmy_hello_tableWHEREupdat

Mysql占用过高CPU时的优化手段

慢查询日志,将那些执行时间过长且占用资源过多的SQL拿来进行explain分析,导致CPU过高,多数是GroupBy、OrderBy排序问题所导致,然后慢慢进行优化改进。比如优化insert语句、优化groupby语句、优化orderby语句、优化join语句等等;3)考虑定时优化文件及索引;4)定期分析表,使用optimizetable;

TiDB RC4 Release

TiDBSQL查询优化器重构更好的支持TopN查询支持Join算子根据代价自动选择更完善的ProjectionEliminationSchema版本检查区分Table,避免DDL干扰其他正在执行的事务支持BatchIndexJoin

MySQL优化总结

★【单表优化】思路【表设计】开始,字段尽量精确,避免过多字段,避免null。【存储引擎】选择好。【索引】设计好。【查询优化】,between和exists优于in的使用;unionall比union的效率高。【表分区】的使用。上面属于单表优化的思路。如果还不能满足