MySQL索引优化与查询优化(一)

150 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

本文参考自宋红康老师的课程

索引优化与查询优化

可以进行数据库调优的维度:

  • 索引失效、没有充分利用到索引——索引建立
  • 关联查询太多JOIN(设计缺陷或不得已的需求)——SQL优化
  • 服务器调优及各个参数设置(缓冲、线程数等)——调整my.cnf
  • 数据过多——分库分表

SQL查询优化技术分为物理查询优化逻辑查询优化

  • 物理查询优化是通过索引表连接方式等技术来进行优化,需要掌握索引的使用
  • 逻辑查询优化就是通过SQL等价变换提升查询效率

1.数据准备

学员表插50万条,班级表插1万条。

2.影响索引的案例

SQL语句是否使用索引和数据库版本数据量数据选择度都有关系。

2.1 全值匹配

2.2 最佳左前缀法则

对于多列索引,过滤条件要使用索引必须按照索引建立时的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法被使用。如果查询条件中没有使用这些字段中的第一个字段时,联合索引不会被使用。

2.3 主键插入顺序

2.4 计算、函数、类型转换(手动或自动)导致索引失效

例如:

SELECT SQL_NO_CACHE * FROM student WHERE LEFT(student.name,3) = 'abc';

SELECT SQL_NO_CACHE id, stuno, NAME FROM student WHERE stuno+1 = 900001;

上例需要把索引字段的取值都取出来,然后依次进行表达式的计算来进行条件判断,因此是全表扫描的方式。

SELECT id, stuno, name FROM student WHERE SUBSTRING(name, 1,3)='abc';

2.5 类型转换导致索引失效

例如:

SELECT SQL_NO_CACHE * FROM student WHERE name=123;

下列SQL可以使用到索引:

SELECT SQL_NO_CACHE * FROM student WHERE name='123';

因此设计实体类属性时,一定要与数据库字段类型相对应,否则会出现类型转换的情况。

2.6 范围条件右边的列索引失效

例如:

SELECT SQL_NO_CACHE * FROM student

WHERE student.age=30 AND student.classId>20 AND student.name = 'abc' ;

只会用到age。

SELECT SQL_NO_CACHE * FROM student

WHERE student.age=30 AND student.name = 'abc' AND student.classId>20 ;

可以用到age和name。

应用开发中的范围查询,比如金额查询、日期查询,应该放到where的最后。

2.7 不等于(!=或<>)索引失效

2.8 is null可以使用索引,is not null、not like无法使用索引

设计数据表的时候最好将字段设置为NOT NULL,将int类型字段默认值设置为0,字符型默认值设置为''。

2.9 like以通配符%开头索引失效

2.10 OR前后存在非索引的列索引失效

or前后的两个条件中的列都是索引时,查询中才会使用索引。因为存在or的前后不是索引时就要进行全表扫描,所以不进行索引查询,直接全表扫描。

2.11 数据库和表的字符集统一使用utf8mb4

统一使用utf8mb4(5.5.3版本以上支持)兼容性更好,统一字符集可以避免由于字符集转换产生的乱码。不同的字符集进行比较前需要进行转换会造成索引失效。