|10分钟掌握MySQL的索引查询优化技巧( 四 )


冗余索引和重复索引不同 , 比如某个索引是(A,B) , 另一个索引是(A) , 这叫冗余索引 , 前者可以代替后者 , 后者不可以代替前者的作用 。 但是(A,B)和(B)以及(A,B)和(B,A)不算冗余索引 , 起作用谁也代替不了谁 。
如果一个表中已经存在索引(A) , 现在又想创建索引(A,B),那么只需扩展就的索引就可以 , 没有必要创建新的索引 。 需要注意的是如果已经存在索引(A) , 那么也没有必要在创建索引(A,ID) , 其中ID指主键 , 因为索引A默认已经包含了主键了 , 也算是冗余主键 。
但是 , 有时候 , 冗余索引也是可取的 , 假设已经存在索引(A) , 将其扩展为(A,B)后 , 因为B列是一个很长的类型 , 导致用A单独查询时没有以前快了 , 这时可以考虑新创建索引(A,B) 。
不使用的索引
不使用的索引徒然增加insert、update和delete的效率 , 应该及时删除
索引使用总结
索引的三星原则:

  • 索引将查询相关的记录按顺序放在一起则得一星
  • 索引中的数据顺序和查询结果的排序一致则得一星
  • 索引中包含了查询所需要的全部列则得一星
第一个条原则的意思是where条件中查询的顺序和索引是一致的 , 就是前面说的从左到右使用索引 。
索引不是万能的 , 当数据量巨大时 , 维护索引本身也是耗费性能的 , 应该考虑分区分表存储 。
查询优化
查询慢的原因
是否向数据库请求了多余的行
比如应用程序只需要10条数据 , 但是却向数据库请求了所有的数据 , 在显示在UI上之前抛弃了大部分数据 。
是否向数据库请求了多余的列
比如应用程序只需要展现5列 , 但却通过select * from 把全部的列都查了出来
是否重复多次执行了相同的查询
应用程序是否可以考虑一次查询然后缓存 , 后面的用到时可以使用第一次查询出来的记录 。
MySQL是否在扫描额外的记录
通过查看执行计划可以大概了解需要扫描的记录数 , 如果这个数字超出了预期 , 尽可能通过添加索引、优化SQL(就是本节的重点) , 或者改变表结构(如新增一个单独的汇总表 , 专门供某个语句查询用)来解决 。
重构查询的方式
  • 将一个复杂的查询分解成多个简单的查询
  • 将大的查询切分成小的查询 , 每次查询功能一样 , 只完成一小部分
  • 分解关联查询 。 可以将一个大的关联查询改成分别查询若干个表 , 然后在应用程序代码中处理
杂七杂八
优化count()
Count有两个作用 , 一是统计指定的列或表达式 , 二是统计行数 。 如果参数传入一列名或者是一个表达式 , 那么count会统计所有结果不为NULL的行数 , 如果参数是* , 那么count会统计所有行数 。 这里有一个传表达式的例子:
SELECT count(name like 'B%') from people
  • 可以使用近似值优化来代替count() , 如执行计划中的行数 。
  • 索引覆盖扫描
  • 增加汇总表
  • 增加内存缓存系统记录数据条数
关联查询的优化
  • MySQL优化器关联表查询是这样进行的 , 比如有两个表A和B通过c列关联 , MySQL会遍历A表 , 然后根据遍历到的c列的值去B表中查找数据 。 综上所述 , 通常 , 如无只需要给B表的c列加上索引即可
  • 确保order by和group by涉及到的列只属于一个表 , 这样才有可能发挥索引的作用
优化子查询
对于MySQL5.5及以下版本 , 尽量用连接代替子查询 。
优化group by、distinct
如果可能 , 尽量对主键施加这两种操作 。
优化limit , 比如有SQL
SELECT * from sa_stockinfo ORDER BY StockAcc LIMIT 400, 5MySQL优化器会查找405行所有列数据然后丢弃400 。 如果能利用覆盖索引查询则不必查询出这么多列 , 先修改为:


推荐阅读