暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

mysql执行计划中的using intersect如何理解

3291


前段时间,在处理线上慢sql时,遇到过一起因为使用了using Intersect导致性能问题的case,当时会比较疑惑,查了一些才搞明白了。

我们知道Using Intersect并不常见,一般我们在explain的extra字段中更多的看到是:Using index、Using where、Using filesort 、Using tempory等,Using intersect相对少见。

今天我们就来看下,Using Intersect是什么含义吧。

上次遇到的case,我没有记录下来,所以没办法拿它举例了,不过我从stackoverflow看到过一个类似的问题,今天就以这个帖子的例子来说明一下吧。

链接如下:https://stackoverflow.com/questions/4526686/why-would-mysql-use-index-intersection-instead-of-combined-index

使用如下sql进行查询:

SELECT id FROM tbl
WHERE rel = 3 AND type = 3
ORDER BY created;

tbl表中有三个索引,idx_type_rel_created(type, rel, created)、idx_type(type)、idx_rel。

在查看该条sql的执行计划时,发现该sql使用到了Using Intersect(idx_type, idx_rel),而没有使用idx_type_rel_created(type, rel, created)。直觉上,应该用到三个字段的联合索引才对。

mysql> EXPLAIN
    -> SELECT id FROM tbl
    -> WHERE rel = 3 AND type = 3
    -> ORDER BY created\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tbl
         type: index_merge
possible_keys: idx_type,idx_rel,idx_rel_type_created
          key: idx_type,idx_rel
      key_len: 1,2
          ref: NULL
         rows: 4343
        Extra: Using intersect(idx_type,idx_rel); Using where; Using filesort

那么,Using Intersect是在内部是如何做的呢?

Using Intersect是指会在查询时对使用到的索引执行同步扫描分别获取数据集,并对所获得的数据集取交集。

在上述的例子中,则是分别使用idx_type索引、idx_rel索引获取数据集,并对获取数据集的交集。

这样的实现是可能出现性能问题的,比如其中某个索引的效率不高时,或者当内存不足以容量数据集时,都可能会导致这种执行计划执行缓慢。Using Intersect不一定会比联合索引或者单列索引执行效率高。

去解释为什么会选择Using Intersect,而不是联合索引会比较困难,这部分涉及到mysql底层的优化器逻辑。我们今天只讲下当遇到这种情况导致的慢sql时,我们要如何解决问题?

有几种方式:

1.关闭index_merge_intersection。

SET optimizer_switch = 'index_merge_intersection=off'

2.删除不需要的单列索引。在上述的例子中,我们可以看出来,idx_type索引是没有必要加的,因为已经有了联合索引idx_type_rel_created。

3.暂时设置不需要的索引设置为隐藏。

如果我们担心直接删除索引有风险,可以暂时将没有用的索引设置为隐藏。mysql 8.0开始支持隐藏索引(invisible index),也称为不可见索引。隐藏索引不会被优化器使用。

使用ALTER TABLE ... ALTER INDEX语句的VISIBLE或者INVISIBLE选项修改已有索引的可见性:

ALTER TABLE table_name ALTER INDEX idx_name VISIBLE; -- 将索引设置为可见
ALTER TABLE table_name ALTER INDEX idx_name INVISIBLE; -- 将索引设置为隐藏


参考文档: 

https://dev.mysql.com/doc/refman/8.0/en/index-merge-optimization.html#index-merge-intersection 

https://www.modb.pro/db/29619

https://stackoverflow.com/questions/4526686/why-would-mysql-use-index-intersection-instead-of-combined-index


点个“赞 or 在看” 你最好看!

喜欢,就关注我吧!




👇👇👇 谢谢各位老板啦!!!

文章转载自PostgreSQL运维技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论