慢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 瓶颈以及数据过多带来的读写性能问题。

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

相关推荐
霖烟易辞5 小时前
MySQL中的DDL语句
数据库·mysql·ddl
阿猿收手吧!5 小时前
【MySQL】表的操作{创建/查看/修改/删除}
数据库·mysql
超维Ai编程5 小时前
mysql从入门到精通
数据库·mysql
心死翼未伤6 小时前
【MySQL基础篇】多表查询
android·数据结构·数据库·mysql·算法
刘铸纬6 小时前
Golang中defer和return顺序
开发语言·后端·golang
多多*7 小时前
每天一道面试题之浅浅讲一下java5中的自动装箱和自动拆箱
java·开发语言·spring boot·后端·spring
江湖十年7 小时前
Go 语言中的结构体内存对齐你了解吗?
后端·go
passion更好8 小时前
IT专业入门,高考假期预习指南
java·前端·人工智能·后端·python·机器学习·高考
0nePiece8 小时前
MySQL右连接详解
数据库·mysql
周六放风筝8 小时前
mysql使用group_concat拼接
数据库·mysql