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 强制索引写法
## 会使索引失效
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;
## Mysql 的写法中,非常不建议子查询写法,而应该尽量用 join 方式替换子查询写法selectsum(t.money)from students
join(select payments.stu_id,payments.money
from payments
where payments.is_paid=1and payments.is_canceled=0and 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 中 selectsum(payments.money)from students
join payments on students.id=payments.stu_id
where payments.is_paid=1and payments.is_canceled=0and payments.money>0and students.created_at>='2021-05-01'and students.created_at<'2021-06-01';
# 不建议写法select u.id
from users u
where u.updated_at >'2021-05-20 12:00:00'and u.id notin(select a.user_id from users_account_number a);# 优化写法select u.id
from users u
leftjoin users_account_number a on u.id=a.user_id
where u.updated_at >'2021-05-20 12:00:00'and a.user_id isnull;