MySQL索引优化总结

上一篇 / 下一篇  2017-10-31 08:28:28 / 个人分类:数据库

     索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。常见比喻是数据库索引好比是一本书前面的目录,能加快数据库的查询速度。那么为什么查索引比查记录要快呢?一是索引的算法不必整个索引扫描后才能定位到记录而扫描记录则必须全部扫描完,另外一个索引字段少文件小加载进内存更快甚至常驻内存。《高性能MySQl》书中提到MySQL索引对某个查询是否合适的三星索引评估准则,索引将相关行放在一起(避免扫描更多的索引)则可获取一星,返回结果都在索引中(避免再查表) 则获取两星,索引顺序与查询要求的返回顺序相同(避免再排序)则获得三星,优化时可参考朝这3个方面去优化。

     是否需要创建索引?1、索引并不是越多越好,特别是OLTP型的,因为更新(插入、删除、更新)数据时均可能要更新索引,那么整体更新时间就增加了,一般情况下索引越多更新数据越慢。2、数据量不多(一般不上万,还要跟表的关,如相当多字段又另当别论了)时也可不必创建索引,因为直接扫描数据可以比扫描索引再找数据更快。3、如果字段的索引基数很小,创建索引也没太多意义,甚至更慢。4、频繁更新的字段建议不使用索引,因为更新时也要更新索引,甚至导致B-Tree或B+Tree的分裂重组则更慢了。5、字段不在where中出现是不需要添加索引, where后含IS NULL   like ‘%输入符%’等条件,也不建议使用索引,因为 like "%_" 百分号在前不走索引, B-tree索引 is null不走索引(is not null会走,位图索引 is null,is not null 则都会走索引)6、 where 子句里对索引列使用不等于(<>),要看字段的数据情况,因为很多时候覆盖索引比直接扫描更慢,可能不走索引。

     如何创建索引?创建索引的方式一般有如下3种:1、创建索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);2、修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);3、创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) )。创建索引时首先需要分析确认是否需要创建索引(参考上文),除了where,关联查询时join的字段一般也需要添加索引。然后考虑是创建单索引还是组合索引,注意索引的最左前缀原则即查询条件必须包括索引的最左部分。最后创建索引后通过查看执行计划验证是否有走索引,或通过强制走索引的方式验证是否有提高效率。
     索引是否有应用?创建完索引后还需要考虑此索引面向哪些查询,是否都有效(是否应用及效率是否有提高)。 MySQL查询优化器是基于代价(cost-based)的查询方式,根据查询语句依据多种索引,计算查询需要的代价,从而选择最优的索引方式生成查询计划。所以可能出现有索引却并未应用上的情况,不应用的场景总结主要如下:
  1. 如果条件中有or,即使其中有部分条件带索引也不会使用。要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引(出现索引合并的话可能性能理差)。
  2. 组合索引,要符合最左前缀才会应用。
  3. like查询是以%开头不会应用索引。
  4. where 子句里对索引列上有数学运算,用不上索引。
  5. where 子句里对有索引列使用函数,用不上索引。
  6. 如果mysql估计使用全表扫描要比使用索引快,则不使用索引。如查询的数量是大表的大部分,应该是30%以上;或是小表。
  7. 统计数据不真实,需要用analyze收集统计信息
  8. 隐式转换导致索引失效,也是开发中经常会犯的错误。由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给数据库,这样会导致索引失效.
  9. not in ,not exist可能不会用索引,参数6。
  10. B-tree索引 is null不走索引(is not null会走,位图索引 is null,is not null 则都会走索引)






TAG:

 

评分:0

我来说两句

Open Toolbar