如果查询字段是字符型,WHERE条件后建议使用’’,否则导致索引失效
未加’’
EXPLAIN SELECT * FROM student_basic_info sbi WHERE sbi.id = 1;
加’’
EXPLAIN SELECT * FROM student_basic_info sbi WHERE sbi.id = '1';
优化LIKE SQL语句
%位置
查询字段前后都加%,导致索引失效
EXPLAIN SELECT * FROM student_basic_info WHERE stuinfo_name LIKE '%张%';
查询字段后加%,索引生效
EXPLAIN SELECT * FROM student_basic_info WHERE stuinfo_name LIKE '张%';
查询列应该使用具体字段,而不用*
只取所需要的字段,节省资源,减少网络开销。SELECT * 进行查询时,很可能就不会使用覆盖索引,导致回表查询。
反例SELECT * FROM student_basic_info;正例SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info;
如果知道查询结果只有一条或者只要最大、最小的一条记录,建议使用LIMIT 1
SQL语句加上LIMIT 1之后,只要找到一条对应的记录,就不会继续向下扫描了,效率大大提高。如果所查询列是唯一索引,是没有必要加LIMIT 1,加LIMIT 1是为了防止全表扫描,从而提高性能。
反例SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_name = '张三';正例SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_name = '张三' LIMIT 1;
应尽量避免在WHERE条件字句中使用OR来连接条件
使用OR可能会导致索引失效,而从导致全表扫描
对于OR + 没有索引的stuinfo_age这种情况,假设它走了stuinfo_name的索引,但是走到stuinfo_age查询条件的时候,它还得进行全表扫描,额就是需要三步过程:全表扫描+索引扫描+合并,如果它一开始就走全表扫描,直接一遍扫描就可以。MySQL是有自己的优化器的,处于效率与成本考虑,遇到OR条件,索引可能失效,看起来也合情合理。
反例SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_name = '张三' OR sbi.stuinfo_age = '12';正例SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_name = '张三'UNION ALLSELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_age = '12';
应尽量避免在WHERE字句中对字段进行表达式操作,这会导致系统放弃索引而进行全表扫描
反例EXPLAIN SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_age + 1 = 11;正例EXPLAIN SELECT id,stuinfo_name,stuinfo_address FROM student_basic_info sbi WHERE sbi.stuinfo_age = 12;
慎用DISTINCT关键字
DISTINCT关键字一般用来过滤重复记录,以返回不重复的记录。
在查询一个字段或者很少字段的情况下使用,给查询带来优化效果,在查询字段很多的情况下,却会大大降低查询效率。
带DISTINCT的SQL语句CPU时间和占用时间都高于不带DISTINCT的语句。因为当查询很多字段时,如果使用DISTINCT,数据库引擎就会对数据进行比较,过滤掉重复数据,然后这个比较、过滤的过程会占用系统资源,CPU时间。
反例SELECT DISTINCT * FROM student_basic_info sbi;正例SELECT DISTINCT sbi.id,sbi.stuinfo_address FROM student_basic_info sbi;
WHERE字句中考虑使用默认值代替null
并不是说使用IS NULL或者IS NOT NULL就会不走索引,这跟MySQL版本以及查询成本都有关。
如果MySQL优化器发现,走索引比不走索引成本要高,肯定会放弃索引。
条件!=、<>、IS NULL 、IS NOT NULL经常被认为会让索引失效,其实是因为一般情况下,查询的成本高,优化器主动放弃的。
如果把NULL值,换成默认值,很多时候让走索引成为可能。
尽量不要超过5个表以上的连接
- 表连接越多,编译的时间和开销也就越大;
- 把表连接拆成开销较小的几个执行,可读性更高;
- 如果一定需要连接很多表才能得到数据,那么意味这是一个糟糕的设计。
