mysql 进阶 索引优化

文章目录

    • 1 索引失效的情况
      • 1.1 全值匹配
      • 1.2 最佳左前缀法则
      • 1.3 索引无操作
      • 1.4 避免范围索引
      • 1.5 使用覆盖索引
      • 1.6 is null,is not null ,!=,<> 导致索引失效
      • 1.7 like以通配符开头(%abc...)索引失效
      • 1.8 字符串类型不加单引号
      • 1.9 少用or
    • 2 mysql 调优步骤
    • 3 排序优化
      • 3.1 小表驱动大表
      • 3.2 oreder 优化
      • 3.3 filesort 算法
      • 3.4 提高order by的速度
    • 4 索引优点

1 索引失效的情况

查看已建立的索引

show index from staffs;

mysql 进阶 索引优化_第1张图片

1.1 全值匹配

  • 对索引中所有列都指定具体值,该情况下,索引生效,执行效率高。

ps :执行里面的顺序变化时不影响的索引的生效,因为优化器会进行排列

1.2 最佳左前缀法则

如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列

ps:跳过索引中的列后会发生索引部分失效,只有左列索引生效

执行 name或者按照name开头的执行可以发现是ref且是常量即建立索引的第一个字段不能丢失

#explain select * from staffs where name =`July` and age= 23 and pos =dev;
# explain select * from staffs where name =`July` and age= 23 ;
explain  select * from staffs where name =`July`;

执行age则发生了索引失效

explain select * from staffs where age=11;

1.3 索引无操作

不在索引列上做任何操作(计算,函数,类型转换),会导致索引失效而转向全表扫描。

对name索引进行left函数操作,索引失效转为all
ps:left 函数相当于java中的substring

explain select *from staffs where L	EFT(NAME.4)='July';

1.4 避免范围索引

对索引进行范围操作后,后面的索引全部失效

explain select * from staffs where name ='July' AND age>18 and pos='dev';


原本索引字节是140,由于后面索引失效导致了变成了78

1.5 使用覆盖索引

尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致))减少select*

 explain select name,age,pos from staffs where name ='July' AND age=23 and pos='dev';

可以看到只查询索引部分时候,extra会出现using index

1.6 is null,is not null ,!=,<> 导致索引失效

使用is null,is not null,!= ,<>会无法使用索引导致全表扫描。

1.7 like以通配符开头(%abc…)索引失效

like以通配符开头的话会导致索引失效变成全表扫描

like通配符加在后面并不会导致索引失效。

 explain select * from staffs where name like 'July%' ;

like 加在前面则会导致索引失效

explain select * from staffs where name like '%July%' ;

解决方法:

使用覆盖索引进行解决

explain select name from staffs where nmae like '%July%';

注意:select 后面的参数范围不能超过覆盖索引的范围

1.8 字符串类型不加单引号

explain select * from staffs where nmae=6;

**原因:**是由于mysql会进行优化,将int型转为字符型,导致索引失效

1.9 少用or

使用or会导致索引失效


口诀:
全值匹配我最爱,最左前缀要遵守;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
Like百分写最右,覆盖索引不写星;
不等空值还有or,索引失效要少用;
VAR引号不可丢,SQL高级也不难!

2 mysql 调优步骤

  • 慢查询的开启并捕获

  • explain + 慢sql分析

  • show profile 查询sql在mysql服务器里面的执行细节和生命周期的情况

  • sql数据库 服务器的参数调优

3 排序优化

  • mysql 两种排序方式:文件排序或扫描有序索引排序

  • mysql 能为排序与查询使用相同的索引

3.1 小表驱动大表

即小的数据集驱动大的数据集

  • exists
select ...from table where exists(subquery)

该语法可以理解为:将主查询的数据,放到子查询中做条件验证,根据验证结果(true或false)来决定主查询的数据结果是否得以保留

注意:exists只返回true或false ,因此子查询中的select也可以是select 1 或其他

mysql 进阶 索引优化_第2张图片

3.2 oreder 优化

  • 重点应该看order by,后面的顺序是否一直,以及要满足左前缀法则。避免filesort的出现
    注意:如果where 使用索引的左前缀定义为常量则order by 能使用索引(WHERE a = const ORDER BY b,c.)
 explain select 8 from tblA a where age>22 order by age;

  • 乱序(不优化的原因是order by是强制性排序的,顺序改变会导致结果集的改变) 或 跳级都会出现filesort
 explain select * from tblA a where age>22 order by birth,age;

  • 排序的方式(asc,desc)不一致也会导致出现filesort
explain select * from tblA a where age>22 order by age asc,birth desc;

3.3 filesort 算法

产生filesort后会有两中算法

  • 双路排序

    • 读取行指针和order by列,对他们进行排序,然后扫描已经排好的列表,按照列表中的值重新从列表中读取对应的数据。

    • 即从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段

  • 单路排序

    • 从磁盘读取查询需要的所有列,按照order by列在buffer对他们进行排序,然后扫描排序好的列表进行输出,避免了第二次读取效率,把随机io变成了顺序io,但是会占用更多内存。

总结:
单路排序比多路优秀,但是单路是把所有字段都取出,有可能取出的数据的总大小超出 sort_buffer 的容量,会再次进行取出,并会创建tmp文件进行合并排序,导致多次i/o;

3.4 提高order by的速度

  • order by 时select * 是大忌,只取自己有用的数据段

  • 尝试提高sort_buffer_size

  • 尝试提高max_length_for_sort_data

4 索引优点

索引可以让服务器快速的定位到表的指定位置,除此之外,根据索引的数据结构不同,索引还有一些其他作用。
最常见的B-tree 索引按照顺序存储数据,所以mysql可以用来做order by 和group by操作,其中索引存储了实例的列值,某些查询只用索引就能全部完成查找

  • 索引大大减少了服务器需要扫描的数据量
  • 索引可以帮助服务器避免排序和临时表
  • 索引可以将临时io变为顺序io

你可能感兴趣的:(msyql高级,索引,mysql)