前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >解读MySQL 8.0新特性:Skip Scan Range

解读MySQL 8.0新特性:Skip Scan Range

作者头像
用户9184480
发布2024-12-19 10:57:08
发布2024-12-19 10:57:08
1010
举报
文章被收录于专栏:云计算linux云计算linux

MySQL从8.0.13版本开始支持一种新的range scan方式,称为Loose Skip Scan。该特性由Facebook贡献。我们知道在之前的版本中,如果要使用到索引进行扫描,条件必须满足索引前缀列,比如索引idx(col1,col2), 如果where条件只包含col2的话,是无法有效的使用idx的, 它需要扫描索引上所有的行,然后再根据col2上的条件过滤。

新的优化可以避免全量索引扫描,而是根据每个col1上的值+col2上的条件,启动多次range scan。每次range scan根据构建的key值直接在索引上定位,直接忽略了那些不满足条件的记录。

示例

下例是从官方文档上摘取的例子:

解读MySQL 8.0新特性:Skip Scan Range_range Index
解读MySQL 8.0新特性:Skip Scan Range_range Index

也可以从optimizer trace里看到如何选择的skip scan:

解读MySQL 8.0新特性:Skip Scan Range_range Scan_02
解读MySQL 8.0新特性:Skip Scan Range_range Scan_02

我们从innodb的角度来看看这个SQL是如何执行的,我们知道每个index scan都会走到ha_innobase::index_read来构建search tuple,上述查询的执行步骤:

  • 第一次从Index left side开始scan
  • 第二次使用key(1,40) 扫描index,直到第一个range结束
  • 使用key(1), find_flag =HA_READ_AFTER_KEY, 找到下一个Key值2
  • 使用key(2,40),扫描Index, 直到range结束
  • 使用Key(2),去找大于2的key值,上例中没有,因此结束扫描

代码注入了日志,打印search_tuple(dtuple_print())

解读MySQL 8.0新特性:Skip Scan Range_分库分表_03
解读MySQL 8.0新特性:Skip Scan Range_分库分表_03

从上述描述可以看到使用skip-scan的方式避免了全索引扫描,从而提升了性能,尤其是在索引前缀列区分度比较低的时候

条件

skip scan可以通过Hint或者optimizer_switch来控制(skip_scan),默认是打开的。根据worklog的描述,对于如下query:

解读MySQL 8.0新特性:Skip Scan Range_分库分表_04
解读MySQL 8.0新特性:Skip Scan Range_分库分表_04

需要满足如下条件才能使用skip scan:

解读MySQL 8.0新特性:Skip Scan Range_mysql 8.0_05
解读MySQL 8.0新特性:Skip Scan Range_mysql 8.0_05

ref: get_best_skip_scan()

当skip scan拥有更低的cost时,会被选择,计算cost的函数是cost_skip_scan(),由于索引统计信息中已经基于不同的前缀列值估算了distinct value的个数(rec_per_key), 可以基于此去预估可能需要读的行数。 更具体的可以参考wl#11322中的描述,笔者对此不甚了解,故不做笔墨ref: cost_skip_scan()

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档