有哪些方式优化慢 SQL?

简介: 慢 SQL 优化主要包括 SQL 语句和数据库设计两方面。应避免使用 `SELECT *`,只选择必要列;对深分页进行优化,如延迟关联或使用 ID 偏移量;合理使用索引,如覆盖索引、避免 `OR` 查询和不等于操作符;优化 JOIN 操作,减少多表关联;并利用索引排序、条件下推等方式提升查询效率。

慢 SQL 的优化,主要从两个方面考虑,SQL 语句本身的优化,以及数据库设计的优化。

避免不必要的列

SQL 查询的时候,应该只查询需要的列,而不是包含额外的列,像select *这种写法应该尽量避免。

分页优化

在数据量比较大,分页比较深的情况下,需要考虑分页的优化。

sql

体验AI代码助手

代码解读

复制代码

 select * from tabel where type = 2 and level = 9 order by id asc limit 100000,10;
  • 延迟关联
    先通过where条件提取出主键,在将该表与原数据表关联,通过主键 id 提取数据行,而不是通过原来的二级索引提取数据行

css

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 select a.* from table a,
 (select id from table where type = 2 and level = 9 order by id asc limit 100000,10) b
 where a.id = b.id;
  • id 偏移量
    偏移量就是找到 limit 第一个参数对应的主键值,根据这个主键值再去过滤并 limit

sql

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 select * from table where id >
 (select id from table where type = 2 and level = 9 order by id asc limit 190 );

索引优化

合理的设计和使用索引,是优化慢 SQL 的利器。

  • 利用覆盖索引
    InnoDB 使用二级索引查询数据时会回表,但是如果索引的叶节点中已经包含要查询的字段,那它没有必要再回表查询了,这就叫覆盖索引,还有一个简单的理解查询列都是索引列。

csharp

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 select b from test where a = "wanna";

css

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 alter table test add index idx_a_b (a,b);
  • 避免使用 or 查询
    在 MySQL 5.0之前的版本要尽量避免使用 or 查询,可以使用 union 或者子查询来替代,因为早期的 MySQL 版本使用 or 查询可能会导致索引失效,高版本引入了索引合并,解决了这个问题,不过建议大家在实际使用中还是规范写法,能不用就少用。
  • 避免使用 != 或者 <> 操作符
    SQL 中,不等于操作符会导致查询引擎放弃查询索引,引起全表扫描,即时比较的字段上有索引
    解决方法:通过把不等于操作符改成 or,可以使用索引,避免全表扫描

bash

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 id <> 'aaa' ===> id > 'aaa' or id < 'aaa'
  • 适当使用前缀索引
    适当的使用前缀索引,可以降低索引的控件占用,提高索引的查询效率。
    比如,邮箱的后缀都是固定的@xxx.com,那么类似这种后面几位为固定值的字段就非常适合定义为前缀索引

sql

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 alter table test add index dix_emaile_prefix (email(6));
  • 需要注意的是,前缀索引也存在缺点,MySQL 无法利用前缀索引做 order bygroup by操作,也无法作为覆盖索引。
  • 避免列上函数运算
    要避免在列字段上进行算术运算符或其他表达式运算,否则可能会导致存储引擎无法正确的使用索引,从而影响了查询的效率。

csharp

  • 体验AI代码助手
  • 代码解读
  • 复制代码
 select * from test where id + 1 = 50;
 select * from test where month(updateTime) = 7;
  • 正确的使用联合索引
    使用联合索引的时候,注意最左匹配原则。

JOIN 的优化

  • 优化子查询
    尽量使用 join 语句来替代子查询,因为子查询是嵌套查询,而嵌套查询会新建创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,同时对于返回结果集比较大的子查询,其对查询性能的影响更大。
  • 小表驱动大表
    关联查询的时候要拿小表去驱动大表,因为关联的时候,MySQL 内部会遍历驱动表,再去连接被驱动表。

sql

  • 体验AI代码助手
  • 代码解读
  • 复制代码
select name from 小表 left join 大表;
  • 适当增加冗余字段
    增加冗余字段可以减少大量的连表查询,因为多张表的连表查询性能很低,所有可以适当的增加冗余字段,以减少多张表的关联查询,这是以空间换时间的优化策略。
  • 避免使用 JOIN 关联太多表
    《阿里巴巴 Java 开发手册》规定不要 join 超过三张表,第一 join 太多降低查询的速度,第二 join 的 buffer 会占用更多的内存。

排序优化

  • 利用索引扫描做排序
    MySQL 有两种方式生成有序结果:一是对结果集进行排序的操作,而是按照索引顺序扫描得出的结果,索引是排好序的数据结果,自然是有序的。
    但是如果索引不能覆盖查询所需列(覆盖索引),就会没扫描一条记录回表查询一次(逐个获取),这个读操作是随机 IO,通常会比顺序全表扫描还慢,有时会直接放弃使用索引转为全表扫描。
    因此,在设计索引时,尽可能使用同一个索引既满足排序又用于查找行。

css

  • 体验AI代码助手
  • 代码解读
  • 复制代码
-- 索引(a,b,c)
select b,c from test where a like 'aa%' order by b,c;
  • 只有当索引的列顺序和order by子句的顺序完全一致,并且所有列的排序方向都一样时,才能够使用索引来对结果做排序。

UNION 优化

  • 条件下推
    MySQL 处理 union 的策略是先创建临时表,然后将各个查询结果填充到临时表中最后再来做查询,很多优化策略在 union 查询中都会失效,因为它无法利用索引。
    所以需要将wherelimit等子句下推到 union 的各个子查询中,以便优化器可以充分利用这些条件进行优化。
    此外,除非确实需要服务器去推,一定要试用union all,如果不加all关键字,MySQL 会给临时表加上 distinct选项,这会导致对整个临时表做唯一性检查,代价很高。


转载来源:https://juejin.cn/post/7485764495927967794

相关文章
SpringBoot之文件上传(单文件与多文件上传的使用)
SpringBoot之文件上传(单文件与多文件上传的使用)
551 1
|
SQL 关系型数据库 MySQL
解决sql插入字符串中包含‘单引号问题
解决sql插入字符串中包含‘单引号问题
1842 2
解决sql插入字符串中包含‘单引号问题
|
12月前
|
存储 NoSQL Dubbo
Java主流分布式解决方案多场景设计与实战
本文介绍了Java领域的主流分布式技术,涵盖分布式服务框架(如Dubbo、Spring Cloud)、分布式数据存储(如Redis、MongoDB)、分布式锁(如ZooKeeper、Redisson)及分布式事务(如Seata、Hmily),并通过电商项目案例分析了这些技术在实际开发中的应用,帮助开发者应对高并发与大数据挑战。
510 0
|
11月前
|
人工智能 监控 中间件
如何用go语言实现类似AOP的功能
本文介绍了如何在 Go 语言中借鉴 Java 的 AOP(面向切面编程)思想,通过 Gin 框架的中间件和函数包装机制实现日志记录、权限校验等横切关注点与业务逻辑的解耦。内容涵盖 AOP 的优点、Go 中的实现方式、Gin 中间件与 AOP 的异同,帮助开发者提升代码模块化与可维护性。
407 0
|
12月前
|
人工智能 安全 调度
Python并发编程之线程同步详解
并发编程在Python中至关重要,线程同步确保多线程程序正确运行。本文详解线程同步机制,包括互斥锁、信号量、事件、条件变量和队列,探讨全局解释器锁(GIL)的影响及解决线程同步问题的最佳实践,如避免全局变量、使用线程安全数据结构、精细化锁的使用等。通过示例代码帮助开发者理解并提升多线程程序的性能与可靠性。
338 0
|
人工智能 编译器 Linux
golang交叉编译和条件编译的实际应用
交叉编译是指在一个平台上生成可在另一平台运行的可执行代码。它允许开发者在资源受限或未准备好的目标环境下提前编译程序。条件编译则根据特定条件选择性地编译代码,常用于适配不同运行环境或区分开发与发布版本。两者结合,能有效提升开发效率与程序适配能力。
374 0
|
SQL 缓存 数据库
SQL慢查询优化策略
在数据库管理和应用开发中,SQL查询的性能优化至关重要。慢查询优化不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将详细介绍针对SQL慢查询的优化策略。
|
11月前
|
关系型数据库 MySQL 数据库
为什么 MySQL 不推荐用 Docker 部署?
本文探讨了MySQL是否适合容器化的问题,分析了Docker容器在数据安全、性能瓶颈、状态管理及资源隔离等方面的挑战,并指出目前主流分布式数据库如TDSQL和OceanBase仍倾向于部署在物理机或KVM上。
492 0
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
3548 7
|
存储 算法 NoSQL
微服务和分布式的区别
微服务和分布式的区别
1780 0