乐趣区

关于mysql:五分钟让你明白MySQL是怎么选择索引死磕MySQL系列-六

系列文章

二、毕生挚友 redo log、binlog《死磕 MySQL 系列 二》

三、MySQL 强人“锁”难《死磕 MySQL 系列 三》

四、S 锁与 X 锁的爱恨情仇《死磕 MySQL 系列 四》

五、如何抉择一般索引和惟一索引《死磕 MySQL 系列 五》

如果你对索引的知识点还不太分明,能够间接通过传送门查看咔咔总结的索引知识点。

揭开 MySQL 索引神秘面纱

索引是为减速查问速度,创立的索引也合乎所有规定,但 MySQL 就是不应用现实的索引,导致查问速度变慢并产生大量慢查问记录。

明天就从这个问题来聊聊 MySQL 抉择索引时都做一些什么事件。

一、如何抉择索引

影响优化器的几大因素

一条查问 SQL 执行须要通过连接器、分析器、优化器、执行器,而抉择索引的重任就交给了 优化器

优化器在多个索引中抉择目标是为了找出执行代价最低的计划。

影响优化器抉择无非就这几个因素,扫描行数、是否应用了长期表、是否应用文件排序。

长期表、文件排序这个两个点会在前期文章给大家缓缓引出,明天只聊扫描行数。

扫描行数越少则拜访磁盘数据的次数就越少,耗费的 CPU 资源越少。

那么这个扫描行数是从哪里取的呢?

扫描行数从何而来?

创立索引始终提倡大家给区分度高的列建设索引,在一个索引上不同值的个数称之为基数(cardinality)。

应用 show index from table_name 能够查看每个索引的基数是多少。

索引基数怎么计算

MySQL 应用采样统计的办法,会选出 N 个数据页,每个数据页大小 16kb,接着统计选出来的数据页上的不同值就会失去一个平均值,用平均值在乘以索引的页面数失去的后果就是这个索引的基数。

表数据是继续减少或删减的,统计的这个数据也不是时时变动的,当变更的数据超过 1 / M 时会主动触发从新计算。

这个 M 是依据参数 innodb_stats_persistent 的值选则的,设置为 on 值为 10,设置为 off 值为 16。

索引基数通过这种形式计算不是精准的但也差不了多少

为什么优化器抉择了扫描行数多的索引?

第一种状况

表增删非常频繁,导致扫描行数不精确

第二种状况

假如你主键索引扫描行数是 10W 行,而一般索引须要扫描 5W 行,这种状况就会遇到优化器抉择了扫描行数多的。

在索引那一期文章中晓得主键索引是不须要回表的,找到值间接就返回对应的数据了。

而一般索引是须要先拿到主键值,再依据主键值获取对应的数据,这个过程优化器抉择索引时须要计算的一个老本。

如何解决这种状况

扫描行数不精确时能够执行 analyze table table_name 命令,从新统计索引信息,达到预期优化器抉择的索引。

二、索引抉择异样如何解决

计划一

在 MySQL 中提供了 force index 来强制优化器应用这个索引。

应用办法:select * from table_name force index (idx_a) where a = 100;

但别误会 force index 的应用办法,之前在代码中看到这样一个案例,给查问列应用了函数操作导致应用不上索引,而后这哥们就间接应用 force index,必定不行的哈!

当优化器没有正确抉择索引时是能够应用这种计划来解决。

毛病

应用 force index 的毛病置信大家也晓得就是太死板,一旦索引名字改变就会生效。

计划二

删掉误选的索引,简略粗犷,很多索引建设其实也是给优化器的一个误导,间接删掉即可。

计划三

批改 SQL 语句,被动疏导 MySQL 应用冀望的索引,个别状况这种做法应用的很少除非你对系统非常相熟,否则尽量少操作。

三、总结

优化器抉择索引首先会依据扫描行数再由执行老本决定。

当索引统计信息不精确时,应用 analyze table 解决。

优化器抉择了谬误的索引,只用 force index 来疾速改正,再通过优化 SQL 语句来疏导优化器抉择正确的索引,最暴力的手法是间接删除误选的索引。

保持学习、保持写作、保持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮忙,我是咔咔,下期见。

退出移动版