概述
相信搭建都知道数据库的常见优化方式,就是建立索引;但是何时建立索引、那些字段需要建立索引,索引是否生效,这些都应该是我们需要关注的问题。
Cardinality统计
我们都知道MySQL使用的是B+树索引,既某个字段的取值范围很广,几乎没有重复(高选择性),则使用B+树索引是最适合的。
mysql>SHOW INDEX FROM table;
通过上面的语句可以看到,对table表中存在的索引,其中有个Cardinality值非常关键,表示索引中不重复记录数量的预估值。当然Cardinality是一个预估值而不是一个准确值,但也足够用来判断当前字段是否适合创建索引。
索引提示
虽然我们通过上述条件建立了适合的字段为索引,但是在某些情况下,当执行EXPLAIN命令进行SLQ语句分析时,会发现优化器并没有选择索引去查找数据,而是通过全表扫描来得到数据。
mysql>EXPLAIN SELECT * FROM table_user WHERE mobile = '13866668888' ;
当然建立合理有效的索引之后,发生全表扫描的情况非常低。尽管如此,MySQL数据库支持索引提示(INDEX HINT),显式地告诉优化器使用哪个索引。总结一下,有两种情况可能需要用到索引提示:
1、MySQL数据库的优化器错误地选择了某个索引,导致SQL语句运行的很慢(这种情况非常少见,绝大部分情况下索引工作都非常高效和正确)。
2、某个SQL语句可以选择的索引非常多,这时优化器选择执行计划时间的开销可能会大于SQL语句本身。
USE INDEX
USE INDEX会提示数据库选择使用某个索引,但优化器实际上使用哪个索引,还是会自己的判断进行。如下面语句,提示使用mobile这个索引来查找数据:
mysql>SELECT * FROM table_user USE INDEX(mobile) WHEREmobile = '13866668888';
FORCE INDEX
FORCE INDEX会强制要求MySQL使用指定的索引。示例语句如下:
mysql>SELECT * FROM table_user FORCE INDEX(mobile) WHERE mobile = '13866668888';
Multi-Range Read优化(MRR)
Multi-Range Read优化的目的是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问,这对IO-bound类型的SQL查询语句可带来性能极大的提升。
mysql>SET @@optimizer_switch='mrr=on,mrr_cost_based=off';
将mrr设为on,mrr_cost_based设为off,来启用Multi-Range Read优化。还可以通过参数read_rnd_buffer_size来控制键值缓冲区大小,当大于该值时,则执行器对已经缓存的数据根据RowID进行排序,并通过RowID来取得行数据。
mysql>SELECT @@read_rnd_buffer_size;
Index Condition Pushdown(ICP)优化
这里说个题外话,ICP优化同样是MySQL 5.6之后开始支持的一种根据索引进行查询的优化方式。ICP优化支持range、ref、eq_ref、ref_or_null类型的查询,当优化器选择ICP优化时,可在执行计划的列Extra看到Using index condition提示。
总结
本篇介绍了一些数据库的优化策略,还有索引的优化策略,希望在日后的面试和工作中可以帮助到大家。