本文已参与「新人创作礼」活动,一起开启掘金创作之路
本文参考自宋红康老师的课程
索引优化与查询优化
可以进行数据库调优的维度:
- 索引失效、没有充分利用到索引——索引建立
- 关联查询太多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版本以上支持)兼容性更好,统一字符集可以避免由于字符集转换产生的乱码。不同的字符集进行比较前需要进行转换会造成索引失效。