每日一题
SQL 优化的步骤
在工作中经常会遇到sql执行效率低的问题,在面试中也经常被问到查询效率低该如何优化,在下面较少几种优化的技巧与方式
慢sql的定位
可以通过下面几种方式进行慢sql的定位
- 启动慢sql查询日志定位执行效率较低的sql语句
- Druid监控统计功能
- 云数据库厂商提供的监测功能
分析执行计划
通过 explain 分析执行计划
其中 type 表示表的连接类型
- system:表中只有一行,即常量表
- const :单表中最多只有一个匹配行,例如 主键和唯一索引
- eq_ref : 多表连接中使用 主键或唯一索引
- ref:多表连接中使用 普通索引
- range:单表中的范围查询 一般是带有 between 或者 where > 的查询, in() 和 or 列表 也会显示为范围查找。然而两者是不同的访问类型
- index: 对于前面的每一行,都通过查询索引来得到数据
- ALL:对于前面的每一行,通过全表扫描来得到数据
通过分析执行计划可以对sql进行相关优化,比如:
- sql 是否按照预期执行,是否有索引失效的存在
- 索引创建的是否合理,应优先考虑索引覆盖的场景
- sql 书写是否存在问题
等等
sql 层面优化技巧
- 不推荐使用 select * 导致 多余的io操作
- 使用小表驱动大表
- 使用 limit 代替 min 、 max
- in 和 exist 正确选择
- 通过索引过滤进行高效的分页
- 使用连接查询代替子查询
- join表的数量不应该超过三个 特殊情况可以在业务逻辑中处理 , 因为 join 不需要创建临时表
- 使用 or 时 保证 or 的每一列上都有独立的索引 或者使用 in 代替
- 如果查询包括 GROUP BY 但用户想要避免排序结果的消耗,则可以指定 ORDER BY NULL禁止排序
- 大批量插入数据 使用batch 操作,从同一客户插入很多行,尽量使用多个值表的 INSERT 语句,这种方式将大大 缩减客户端与数据库之间的连接、关闭等消耗
- 设计索引和写sql 优先考虑索引覆盖
定期检查表
- 表是否数据过多 考虑表的拆分 或者 分表
- 表是否经常进行 修改和删除操作,占用锁导致查询变慢,或者可以增大 buffer_pool 的空间
- 表存储是否存在大量硬盘碎片导致查询变慢