1.mysql表优化和避免索引失效原则

表优化

1、单表优化

建立索引

  1. 根据sql的实际解析顺序建立复合索引
  2. 最佳左前缀,保持索引的定义和使用顺序一致

2、多表优化

连接查询

  1. 小表驱动大表:对于双层循环来说,外层循环(数据量)越小,内层循环(数据量)越大,程序性能越高。一般左外连接左表为驱动表,右外连接右表为驱动表,内连接选结果集小的为驱动表。
  2. 索引建立在经常使用的字段上,给被驱动表建立索引
  3. 一般我们将小表当做驱动表(指定了联接条件时,满足查询条件的记录数少表为「驱动表」,未指定联接条件时,行数少的表为「驱动表」)

3、避免索引失效原则

  1. 复合索引,不要跨列或无序使用(最佳左前缀),左边失效右边全部失效。但独立索引无此影响
  2. 复合索引,尽量使用全索引匹配
  3. 复合索引,不能使用不等于(!= <>)或 is null(is not null),否则自身及右侧索引全部失效。独立索引也会失效
  4. 复合索引,一般而言,范围查询( > < in),之后的索引会失效
  5. 不要在索引上进行任何操作(计算、函数、类型转换),否则索引失效
  6. 尽量使用索引覆盖(using index)
  7. like尽量以“常量”开头,不要以“%”开头,否则索引失效
  8. 尽量不要使用or,否则索引失效
  9. 强制使用索引:select * from tabname force index(index_name) where ……
  10. 强制不使用索引:select * from tabname ignore index(index_name) where ……
  11. exists和in的使用,子查询数据集大用exists,主查询数据集大用in
  12. 尽量不要使用 select * ……

4、order by 优化

  1. 双路排序,需要两次IO,先去排序字段进行排序,然后再根据主键查找selet 字段;
  2. 单路排序,把所有字段都读取到sort buffer里面,如果sort buffer(内存)不够大,就会使用到文件排序(磁盘),另外,也只用所有列的总长度小于max_length_for_sort_data时,才会使用单路排序,否则会自动转为双路排序。
  3. 尽量保证排序的一致性(都是升序或降序)
  4. 双路排序:
    读取行指针和order by列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出。
    双路排序的开销可能会非常巨大,因为他会读取表两次,第二次读取会引发大量的随机IO,对于myisam来说,这个代价尤其昂贵,myisam表利用系统调用去提取每行的数据。
  5. 单路排序:
    读取查询需要的所有列,按照order by 列对他们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为它把每一行都保存在内存中了。

5、IN 和Exists的适用场景

  • IN查询在内部表和外部表上都可以使用到索引;
  • Exists查询仅在内部表上可以使用到索引;
  • 当子查询结果集很大,而外部表较小的时候,Exists的Block Nested Loop(Block 嵌套循环)的作用开始显现,并弥补外部表无法用到索引的缺陷,查询效率会优于IN。
  • 当子查询结果集较小,而外部表很大的时候,Exists的Block嵌套循环优化效果不明显,IN 的外表索引优势占主要作用,此时IN的查询效率会优于Exists。
  • 网上的说法不准确,即表的规模不是看内部表和外部表,而是外部表和子查询结果集。
posted @ 2020-12-18 11:02  罐头鱼  阅读(131)  评论(0编辑  收藏  举报