慢sql优化方式大全-看看有没有你不知道

慢sql优化方式

慢 SQL 优化是我们工作和面试中经常遇到的问题。怎么优化网上有很多,但大多数都是基于 explain,去优化 SQL 比较片面也无法解决全部问题。个人对慢 SQL 优化,做了以下这些总结,根据优先级排序。

索引:

索引是最快优化 SQL 的方式,并且基本不需要修改业务代码。我们可以根据 SQL 查询条件的频次给对应的表加上索引,可以通过 explain 查看 SQL 执行的效果来观察添加索引的效果。但需要注意的是,如果索引加的过多,也可能导致数据写入性能下降(插入、更新、删除),存储空间占用增加的问题。

explain需要关注的核心指标有

select_type、type、possible_keys、key、rows、Extra

  • select_type:表示查询中每个select子句的类型,是简单查询还是联合查询还是子查询:
select_type的值 解释
SIMPLE 简单查询(不使用关联查询或子查询)
PRIMARY 如果包含关联查询或者子查询,则最外层的查询部分标记primary
UNION 联合查询(UNION)中第二个及后面的查询
DEPENDENT UNION UNION中的第二个或后面的SELECT语句,取决于外面的查询
UNION RESULT UNION的结果,union语句中第二个select开始后面所有select
SUBQUERY 字查询中的第一个查询
DEPENDENT SUBQUERY 子查询中的第一个查询,并且依赖外部查询
DERIVED 派生表的SELECT, FROM子句的子查询
MATERIALIZED 被物化的子查询
UNCACHEABLE SUBQUERY 一个子查询的结果不能被缓存,必须重新评估外链接的第一行
  • type:表示MySQL在表中查找所需数据的方式。
type的值 解释
system 查询对象表只有一行数据,且只能用于MyISAM和Memory引擎的表,这是最好的情况
const 基于主键或唯一索引查询,最多返回一条结果
eq_ref 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
ref 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
fulltext 全文检索
ref_or_null 表连接类型是ref,但进行扫描的索引列中可能包含NULL值
index_merge 利用多个索引
unique_subquery 子查询中使用唯一索引
index_subquery 子查询中使用普通索引
range 只检索给定范围的行,使用一个索引来选择行
index Full Index Scan,index与ALL区别为index类型只遍历索引树
ALL Full Table Scan, MySQL将遍历全表以找到匹配的行
  • possible_keys:应该或建议使用的索引
  • key:实际使用的索引,没有的情况下为NULL
  • rows:预估扫描了了多少行。
  • Extra:包含一些额外的信息,如是否使用了临时表、是否进行了文件排序、是否进行了优化等。

冗余:

冗余是指存储冗余数据,将原来多个表的数据抽取到一张表,以减少联接和复杂查询的需求,从而提高查询性能。但抽取的表可能会数据过多或者行数据过多导致查询慢,需要根据数据量和业务酌情考虑。也可以将这些数据抽取到列数据库或者 ES 中。

批量处理:

批量写入将多个操作组合成单个事务,而不是执行单个插入或更新操作。这可以减少开销,提高整体吞吐量,特别是处理大型数据集时 。

减小锁粒度:

MySQL在使用InnoDB引擎的情况下 可以采用以下方式减少锁的粒度和时间

  1. 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
  2. 合理设计索引,尽量缩小锁的范围
  3. 尽可能较少检索条件,避免间隙锁
  4. 尽量控制事务大小,减少锁定资源量和时间长度
  5. 尽可能低级别事务隔离

减少复杂查询:

通过将复杂查询拆分为更小,可以简化SQL查询并提高性能。涉及优化联接、减少子查询的数量,或编写查询以更有效地利用索引等。

核心思想是尽可能减少:(行记录扫描)和(临时表)。

常用手段:

•层级合并 减少临时表个数

•条件下推 减少检索行数&临时表大小

•join优化 减少检索行数&临时表大小

•子查询删除 减少临时表个数

•子查询与join的相互转换 减少检索行数

事务处理:

可以采用编程式事务更精准的控制事务进而提高并发性。这包括仔细考虑事务隔离级别、事务边界和事务设计,进而平衡数据一致性和性能。

提升硬件性能:

可以根据负载情况,升级硬件CPU、内存、存储和网络,可以显著提升数据库性能,并注意需要将数据库和应用隔离部署避免相互影响 。

读写分离:

分离读和写可以有效提高可伸缩性。通过将读从库,主库可以专注于处理写入操作,而不会被读请求压垮。并且可以通过扩展从库提高数据库的读 QPS。但要注意读写分离带来的主从延迟,并且无法解决写入性能和数据过多带来的查询慢的问题。

分库:

分三种情况

  1. 垂直分库

根据业务把不同业务的数据,根据数据库隔离存储,降低不同业务之间的影响,可以解决非核心业务影响核心业务。

2.读写分离

每个库数据完全一致,采用读写分离 可以解决减缓数据库读 qps过高,数据库连接不足 和磁盘io瓶颈 无法解决写入性能和数据过多带来的性能的问题

  1. 数据分片 分库

根据自定义算法根据数据分片,每个分片包含数据的子集,可以实现并行处理并可以再提供读写分离提高读性能。可以解决减缓数据库读写 QPS 过高,数据库连接不足和磁盘 IO 瓶颈以及数据过多带来的读写性能问题。

分库分表-具体内容可以参考本人写的下列文章
分库分表详解 上-基础概念
分库分表详解 中- 数据迁移
分库分表详解 下-分库分表方案模版

相关推荐
摇滚侠3 小时前
Spring Boot 3零基础教程,IOC容器中组件的注册,笔记08
spring boot·笔记·后端
程序员小凯6 小时前
Spring Boot测试框架详解
java·spring boot·后端
你的人类朋友6 小时前
什么是断言?
前端·后端·安全
程序员小凯7 小时前
Spring Boot缓存机制详解
spring boot·后端·缓存
闲人编程8 小时前
从多个数据源(CSV, Excel, SQL)自动整合数据
python·mysql·数据分析·csv·存储·数据源·codecapsule
i学长的猫8 小时前
Ruby on Rails 从0 开始入门到进阶到高级 - 10分钟速通版
后端·ruby on rails·ruby
用户21411832636028 小时前
别再为 Claude 付费!Codex + 免费模型 + cc-switch,多场景 AI 编程全搞定
后端
disanleya8 小时前
MySQL默认密码不安全?如何首次登录并强化?
数据库·mysql·安全
花开富贵贼富贵8 小时前
MySQL 核心高级特性
运维·数据库·mysql
茯苓gao8 小时前
Django网站开发记录(一)配置Mniconda,Python虚拟环境,配置Django
后端·python·django