系列文章
二、毕生挚友 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 语句来疏导优化器抉择正确的索引,最暴力的手法是间接删除误选的索引。
保持学习、保持写作、保持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮忙,我是咔咔,下期见。