前言

 Sql语句优化是Mysql性能优化的一部分,我们看下常见Sql语句优化及注意的有哪些。 

一、查询SQL尽量不要使用select *,而是具体字段

  1. 反例

SELECT * FROM user;

     2. 正例

SELECT id,name,tel FROM user

   说明:

  • 只返回需要的字段,节省资源,减少网络开销。
  • 可能用到覆盖索引,减少回表,提高查询效率。

 

二、避免在where子句中使用 or 来连接

  1. 反例

SELECT * FROM user WHERE id = 1 OR name = "song"

2、正例

(1)使用union all

SELECT * FROM user WHERE id = 1 
UNION ALL
SELECT * FROM user WHERE name = "song"

   (2) 或者分开两条sql写

SELECT * FROM user WHERE id = 1

SELECT * FROM user WHERE name = "song"

说明:

  • 使用or可能会使索引失效,从而导致全表扫描。
  • 对于or没有索引的name这种情况,假设它走了id的索引,但是走到name查询条件时,它还得全表扫描。
  • 也就是说整个过程需要三步:全表扫描+索引扫描+合并。如果它一开始就走全表扫描,直接一遍扫描就搞定。
  • 虽然mysql是有优化器的,出于效率与成本考虑,遇到or条件,索引还是可能失效的。

  三、where条件中使用默认值代替null

     1. 反例

SELECT * FROM user WHERE age IS NOT NULL

    2. 正例

SELECT * FROM user WHERE age>0

   说明:

  • 并不是说使用了is null或者 is not null就会不走索引了,这个跟mysql版本以及查询成本都有关。
  • 如果mysql优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 !=,<>,is null,is not null经常被认为让索引失效。Mysql计算如果认为使用索引的时间成本高于全表扫描,比如多次回表,于是mysql宁可全表扫描也不愿意使用索引。
  • 其实是因为一般情况下,查询的成本高,优化器自动放弃索引的。
  • 如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点。

     延伸:

  is null/is not null本身并不会导致不使用索引。在官方文档里有写:

      https://dev.mysql.com/doc/refman/8.0/en/is-null-optimization.html

MySQL can perform the same optimization on col_name IS NULL that it can use 
for col_name = constant_value. 
For example, MySQL can use indexes and ranges to search for NULL with IS NULL.

  意思大致是MySQL可以对col_name IS NULL执行与col_name = constant_value相同的优化。例如,MySQL可以使用索引和范围搜索带有IS NULL。 

四、避免在where子句中使用!=或<>操作符

1、反例

SELECT * FROM user WHERE age !=18

SELECT * FROM user WHERE age<>18

  说明:

  • 使用!=<>很可能会让索引失效。
  • 应尽量避免在where子句中使用!=<>操作符,否则引擎将放弃使用索引而进行全表扫描。