IT评测·应用市场-qidao123.com
标题:
MySQL查询性能优化七种武器之索引潜水
[打印本页]
作者:
海哥
时间:
2022-9-16 17:14
标题:
MySQL查询性能优化七种武器之索引潜水
有读者可能会一脸懵逼?
啥是
索引潜水
?
你给起的名字的吗?有没有索引蛙泳?
这个名字还真不是我起的,今天要讲的知识点就叫
索引潜水(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);
复制代码
where条件中有9个参数,重点关注一下执行计划中的预估扫描行数为279行。
到这里没什么问题,预估的非常准,实际就是279行。
但是,问题来了,当我们在where条件中,再加一个参数,变成了10个参数,预估扫描行数本应该增加,结果却大大减少了。
explain select * from user
where age in (1,2,3,4,5,6,7,8,9,10);
复制代码
一下子减少到了30行,可是实际行数是多少呢?
实际是310行,预估扫描行数是30行,真是错到姥姥家了。
MySQL咋回事啊,到底还能不能预估?
不能预估的话,换其他人!
大家肯定也是满脸疑惑,直到我去官网上看到了一个词语,
索引潜水(Index dive)
。
跟这个词语相关的,还有一个配置参数
eq_range_index_dive_limit
。
MySQL5.7.3
之前的版本,这个值默认是10,之后的版本,这个值默认是200。
可以使用命令查看一下这个值的大小:
show variables like '%eq_range_index_dive_limit%';
复制代码
当然,我们也可以手动修改这个值的大小:
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预估扫描行数更准确,可以选择更合适的索引。
快去检查一下你们的线上配置吧!
文章持续更新,可以微信搜一搜「 一灯架构 」第一时间阅读更多技术干货。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4