因为一条SQL慢查询的思考

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 本文探讨了MySQL中的慢查询问题,包括定义(执行时间过长的SQL语句)、如何查看慢查询(通过`long_query_time`配置)以及其对系统性能的影响。慢查询可能由缺乏索引、大数据量、网络延迟等因素引起。解决和避免慢查询的方法包括优化配置、添加索引、调整查询语句、批量处理数据、分库分表等。文章还强调了索引在提升查询性能中的作用,解释了B+树索引的工作原理,并列举了可能导致索引失效的场景。

  开始之前,我们先思考以下几个问题(下文将围绕以下三个问题展开):

1. 什么是慢查询,查询多少秒以上算是慢查询?

2. 如何解决慢查询和如何避免慢查询?

3. 提升查询性能必知必会


一、慢查询

1.1 什么是慢查询?

mysql 慢查询指的是执行时间过长的 sql 查询语句,影响数据库的性能和用户体验。

1.2 如何查看系统中存在哪些慢查询?

首先开启慢查询监控。

mysql有一个配置是long_query_time,值是数字,单位是秒。当一条SQL语句执行耗时超过long_query_time的值时,mysql就认为这条sql为慢查询SQL。

相当命令如下

// 查看慢查询是否开启
show variables like 'slow_query_log';
// 开启慢查询(值可以是1或on)
set global slow_query_log = 1;
// 关闭慢查询(值可以是1或off)
set global slow_query_log = 0;
// 查看long_query_time值
show variable like 'long_query_time';
// 设置long_query_time值 (单位是秒)
set global long_query_time=5;

image.gif

 注:若用以上命令来配置,则在重启后会失效,若想永久生效可以配置在my.conf中。

 开启了配置之后,通过以下命令获取慢查询SQL的日志路径

show variables like 'slow_query_log_file%'

image.gif

1.3 引起慢查询的原因和影响

在B端的应用系统中容易出现慢查询。B端系统上线一段时间之后,随着数据量越来越大,系统的性能问题也逐步浮水面,最常见的就是因慢查询引起的功能反应速度变慢而使用户体验越来越差。

慢查询可能会引起CPU损耗过高和系统IO压力增加,更严重的情况是整个系统崩溃。

引起慢查询的原因大致归纳如下:

  1. 没有索引或者SQL没有命中索引导致索引失效(思考:为什么会索引失效?
  2. 单表数据量过多,导致查询遇到瓶颈。比如2000万条数据(思考:为什么有些表两千万条数据很快,而有些表两千万条数据就很慢?
  3. 网络速度慢
  4. I/O吞吐量小,形成了瓶颈效应
  5. 热点数据导致单点负载不均衡
  6. 内存不足
  7. 查询结果集的数据量过大
  8. 行锁或表锁
  9. 返回不必要的列

二、如何解决和避免慢查询

  • 提高网速、更换更高容量的硬盘、增加内存或者 cpu 的数量等等
  • 调整配置参数:mysql 有许多参数可以配置,可以根据实际情况调整这些参数,如增加缓存大小、线程池大小等等。
  • 添加索引:索引可以提高查询效率,特别是对于大型表。通过分析慢查询日志或者使用 explain 命令找到需要优化的查询语句,然后为其中涉及的列添加索引(注意不要添加过多的索引)
  • 优化查询语句:合理优化查询语句可以减少查询时间。例如,可以尝试减少子查询的数量,避免使用SELECT *,多表JOIN,避免使用 like '%xxx%' 的模糊查询等。
  • 批量处理数据:有时候大量数据的操作往往比单个数据的操作更有效率。因此,尽可能以批量方式操作数据,如使用 insert .. values() 和 update .. set .. where in() 等。
  • 分库分表:若数据量较大,可能会对单个数据库的性能造成压力。此时可以考虑将数据分散存储到多个数据库中,或者将单张表的数据拆分为多张表来存储。注意,这种方法需要谨慎设计,在实际应用中可能会引入更多的问题。
  • 表中的大字段剥离
  • 字段冗余
  • 减少sql中函数运算与其他计算
  • 修改SQL语句:优化查询语句,避免使用SELECT *、子查询、多表JOIN等不必要的操作。
  • 数据库优化:调整数据库参数、内存占用、磁盘IO等,提高系统性能,增加查询效率。
  • 针对查询频繁的热点数据增加缓存,引入非关系型数据库
  • 主从复制,读写分离,一般情况下,查询的情况比写的情况多,所以考虑将数据库分为主库,从库,主库处理写的操作,从库处理读的操作

     

三、提升SQL性能必知必会

常常听到同事们讨论有关慢查询的问题 “哎这个SQL怎么这么慢,看一下加索引了没有?”

思考:添加索引后为什么查询速度会增加?为什么即使添加索引也不能提升查询速度?

3.1 添加索引提升查询速度

  • 数据内存中比较相比mysql的查询产生io的耗时可忽略不计,所以查询速度取决于查询过程中的IO次数耗时,即提高查询次数的有效方法是减少IO次数(mysql的数据是存储在磁盘中)
  • mysql innoDB引擎索引数据结构是B+tree结构(树节点称为数据叶)
  • 每个数据叶默认大小为16kb(16384)(show VARIABLES like 'innodb_page_size';)
  • 假设我们用bigint做为主键索引大概占8个字节,(B+tree特点)有指向下一个的指针大概占6个字符,则每个数据叶可以存放的索引信息有 16384 / (8 + 6)= 1170个索引信息。
  • 对于主键过引,假设一行数据1kb,则叶子可存16条数据。当B+Tree的高度为h = 2 则数据量为 1170 * 16 = 18720条数据,当B+Tree的高度为 h = 3 则数据量为1170 * 11170 * 16 = 21902400条数据(2190.24万)
  • 对于非主键索引,则叶子节点的索引信息有 16384 /(8+8)= 1024个索引信息。若h=2 则数据量为 1170 * 1024 = 1198080,若h=3 则数据量为 1170*1170*1024 = 1401753600条数据(14亿零175.36万)
  • 结论:
  1. 非主键索引,索引覆盖,14亿条数据情况下只需要3次io即可查询到想要的数据
  2. 主键索引查询,2190.24万条数据情况下只走需要3次io即可查询到想要的数据

思考:非主键索引查询速度快还是主键索引查询速度快?为什么InnoDB的索引用B+Tree结构而不用其他数据结构?

3.2 索引失效场景

  • 前缀模糊查询,如 like 以%开头(为什么失效?)。%是配置所有,配置所有即全表配置,所以索引失效。
  • 使用or操作符。mysql一个表的查询语句中只使用一个索引,涉及两个字段以上,MySQL无法使用索引,会转向全表扫描。
  • 联合索引未使用第一个字段。联合索引生效原则是最左匹配原则。
  • 索引列上使用函数。因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。
  • 隐式转换会使用索引失效。
  • 索引列重复数据非常多。
  • 不等于导致索引失效。
  • 关联查询中关联字段的字符集不同。不同的字符集进行比较前需要进行转换会造成索引失效
  • is null使用索引,is not null不使用索引。

注:后续一起来研究InnoDb B+Tree

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
SQL 监控 关系型数据库
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
【MYSQL高级】Mysql找出执行慢的SQL【慢查询日志使用与分析】
1660 0
|
28天前
|
SQL 缓存 数据库
SQL慢查询优化策略
在数据库管理和应用开发中,SQL查询的性能优化至关重要。慢查询优化不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将详细介绍针对SQL慢查询的优化策略。
|
4月前
|
SQL 关系型数据库 MySQL
【MySQL 慢查询秘籍】慢SQL无处遁形!实战指南:一步步教你揪出数据库性能杀手!
【8月更文挑战第24天】本文以教程形式深入探讨了MySQL慢SQL查询的分析与优化方法。首先介绍了如何配置MySQL以记录执行时间过长的SQL语句。接着,利用内置工具`mysqlslowlog`及第三方工具`pt-query-digest`对慢查询日志进行了详细分析。通过一个具体示例展示了可能导致性能瓶颈的查询,并提出了相应的优化策略,包括添加索引、缩小查询范围、使用`EXPLAIN`分析执行计划等。掌握这些技巧对于提升MySQL数据库性能具有重要意义。
443 1
|
4月前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
129 0
|
4月前
|
SQL 监控 关系型数据库
"SQL性能瓶颈大揭秘:一步步教你揪出慢查询元凶,从根源解决数据库拖沓问题,让应用速度飞起来!"
【8月更文挑战第31天】作为一名数据库管理员或开发者,面对复杂系统时,运行缓慢的SQL查询常常令人头疼。本文将指导你如何诊断并解决这些问题。首先,通过性能监控工具识别出问题查询;其次,利用`EXPLAIN`分析其执行计划,了解索引使用情况;接着,优化查询语句,如使用合适索引、减少JOIN操作等;再者,优化数据库设计,采用分区表或调整硬件资源;最后,持续监控性能并调优。通过这些步骤,可有效提升数据库的整体性能。
83 0
|
6月前
|
SQL 关系型数据库 MySQL
MySQL数据库——索引(3)-索引语法(创建索引、查看索引、删除索引、案例演示),SQL性能分析(SQL执行频率,慢查询日志)
MySQL数据库——索引(3)-索引语法(创建索引、查看索引、删除索引、案例演示),SQL性能分析(SQL执行频率,慢查询日志)
78 2
|
6月前
|
SQL 存储 关系型数据库
慢查询优化方案-SQL篇【JavaPub版】
慢查询优化方案-SQL篇【JavaPub版】
180 0
|
7月前
|
SQL 关系型数据库 MySQL
mysql5.7 慢查询配置 查看sql语句执行时间
mysql5.7 慢查询配置 查看sql语句执行时间
106 1
|
7月前
|
SQL 数据库 开发者
百度搜索:蓝易云【SQL高级之慢查询日志?】
慢查询日志是数据库性能优化中一个重要的工具,通过记录执行时间较长的查询语句,帮助识别和解决数据库中的性能问题。它提供了有价值的信息,帮助开发者和管理员优化查询和提升数据库的性能。
84 6
|
SQL 数据库 Docker
微服务轮子项目(14) - 慢查询SQL
微服务轮子项目(14) - 慢查询SQL
66 0