2

MySQL查询性能优化七种武器之索引潜水 - 一灯架构

 2 years ago
source link: https://www.cnblogs.com/yidengjiagou/p/16565012.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

MySQL查询性能优化七种武器之索引潜水

有读者可能会一脸懵逼?

啥是索引潜水

你给起的名字的吗?有没有索引蛙泳?

image

这个名字还真不是我起的,今天要讲的知识点就叫索引潜水(Index dive)

先要从一件怪事说起:

我先造点数据复现一下问题,创建一张用户表:

CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(100) NOT NULL DEFAULT '' COMMENT '姓名',
  `age` int(11) NOT NULL DEFAULT 0 COMMENT '年龄',
  PRIMARY KEY (`id`),
  KEY `idx_age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

通过一批用户年龄,查询该年龄的用户信息,并查看一下SQL执行计划:

explain select * from user 
where age in (1,2,3,4,5,6,7,8,9);
image

where条件中有9个参数,重点关注一下执行计划中的预估扫描行数为279行。

到这里没什么问题,预估的非常准,实际就是279行。

image

但是,问题来了,当我们在where条件中,再加一个参数,变成了10个参数,预估扫描行数本应该增加,结果却大大减少了。

explain select * from user 
where age in (1,2,3,4,5,6,7,8,9,10);
image

一下子减少到了30行,可是实际行数是多少呢?

image

实际是310行,预估扫描行数是30行,真是错到姥姥家了。

MySQL咋回事啊,到底还能不能预估?

不能预估的话,换其他人!

image

大家肯定也是满脸疑惑,直到我去官网上看到了一个词语,索引潜水(Index dive)

跟这个词语相关的,还有一个配置参数 eq_range_index_dive_limit

MySQL5.7.3之前的版本,这个值默认是10,之后的版本,这个值默认是200。

可以使用命令查看一下这个值的大小:

show variables like '%eq_range_index_dive_limit%';
image

当然,我们也可以手动修改这个值的大小:

set eq_range_index_dive_limit=200;

这个 eq_range_index_dive_limit 配置的作用就是:

当where语句in条件中参数个数小于这个值的时候,MySQL就采用索引潜水(Index dive)的方式预估扫描行数,非常准确。

当where语句in条件中参数个数大于等于这个值的时候,MySQL就采用另一种方式索引统计(Index statistics)预估扫描行数,误差较大。

MySQL为什么要这么做呢?

都用索引潜水(Index dive)的方式预估扫描行数,不好吗?

其实这是基于成本的考虑,索引潜水估算成本较高,适合小数据量。索引统计估算成本较低,适合大数据量。

一般情况下,我们的where语句的in条件的参数不会太多,适合使用索引潜水预估扫描行数。

建议还在使用MySQL5.7.3之前版本的同学们,手动修改一下索引潜水的配置参数,改成合适的数值。

如果你们项目中in条件最多有500个参数,就把配置参数改成501。

这样MySQL预估扫描行数更准确,可以选择更合适的索引。

image

快去检查一下你们的线上配置吧!

文章持续更新,可以微信搜一搜「 一灯架构 」第一时间阅读更多技术干货。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK