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

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

相关推荐
2301_811274313 分钟前
大数据基于Spring Boot的化妆品推荐系统的设计与实现
大数据·spring boot·后端
武子康16 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
黑色叉腰丶大魔王21 分钟前
《MySQL 数据库备份与恢复》
mysql
Ljw...29 分钟前
索引(MySQL)
数据库·mysql·索引
草莓base43 分钟前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
OpsEye1 小时前
MySQL 8.0.40版本自动升级异常的预警提示
数据库·mysql·数据库升级
Ljw...1 小时前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
编程重生之路1 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
i道i9 小时前
MySQL win安装 和 pymysql使用示例
数据库·mysql