1.尽量避免全表扫描,应考虑在 where 和 order by 涉及的列上建立索引

2.被驱动表的关联字段需要创建索引,否则被驱动表会走全表扫描

3.索引遵循最左前缀匹配原则,like 写法只能将 % 放在右边,如 name like ‘掌门学员%’;若 % 放在左边会导致索引失效

4.应尽量避免在 where 子句中使用 !=<> ,not in 操作符,会导致索引失效

5.应尽量避免在 where 子句中使用 or 来连接条件,可尝试拆分为 union/union all

6.可考虑使用 join/left join 关联查询,替代子查询、in/not in 的写法,尽量不要用子查询

7.如果 in 的内容是连续的,可使用 between…and 或者 >….< 替代,改走范围扫描

8.不要在查询字段上使用函数或者表达式,会导致索引失效,可在参数字段上做函数或表达式运算

9.查询时需根据字段定义类型进行传参 ,若参数类型与字段定义类型不一致,会导致索引失效

10.不要使用 select *  写法,只查询需要的列

11.不要在数据库中使用变量 + 分组排序方式构造排序字段,MySQL 需要基于全量数据做排序分组,效率很低

12.通过 limit 方式分页会导致后续分页越来越慢,可取前一次分页的最大 ID 作为下一页参数输入,进行分页

13.不要通过 order by rand() 方式取随机数,效率极低。如果需要取随机数,可以先用随机数方法取得一个整数,然后根据 id>= 该整数即可。

14.禁止不必要的排序,排序操作极耗资源,不要轻易分组排序

15.不要在程序中使用 using index 强制索引写法

使用 union/union all 替换 or 写法

## 会使索引失效
 select count(0)
 from students
 where students.created_at>='2021-05-01'
   or students.referrer_user_id>0;
   
## 优化写法
select count(0)
 from 
 (select id
 from students
 where students.created_at>='2021-05-01'
 union
 select id
 from students
where students.referrer_user_id>0) as t;

使用 join 关联替换子查询、in、exists 写法

## Mysql 的写法中,非常不建议子查询写法,而应该尽量用 join 方式替换子查询写法
select sum(t.money)
 from students
 join 
 (select payments.stu_id,payments.money
 from payments
 where payments.is_paid=1
   and payments.is_canceled=0
     and payments.money>0) as t on students.id=t.stu_id
    where students.created_at>='2021-05-01'
      and students.created_at< '2021-06-01';
      
## 直接使用 join 进行多表关联,并将查询条件写入到 where 中      
 select sum(payments.money)
 from students
 join payments on students.id=payments.stu_id
 where payments.is_paid=1
   and payments.is_canceled=0
   and payments.money>0
   and students.created_at>='2021-05-01'
   and students.created_at< '2021-06-01';      

使用 join/left join 替代 in/exists、not in/not exists 写法

# 不建议写法
select u.id 
 from users u 
 where u.updated_at > '2021-05-20 12:00:00'
	and u.id not in(select a.user_id from users_account_number a);

# 优化写法
select u.id 
 from users u 
 left join users_account_number a on u.id=a.user_id
 where u.updated_at > '2021-05-20 12:00:00'
 and a.user_id is null;

根据字段类型合理传参

#参数类型与字段定义类型不一致
select *
 from users
 where mobile=13199999999;
# 
select *
 from users
 where mobile='13999999999';

不要在查询字段上使用函数或表达式

防止分页过大导致查询越来越慢,可使用id优化