因为一条SQL慢查询的思考

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 本文探讨了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

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6天前
|
SQL 大数据 API
每天一道大厂SQL题【Day08】服务日志SQL统计
每天一道大厂SQL题【Day08】服务日志SQL统计
45 0
|
6天前
|
SQL
常用sql记录
常用sql记录
12 0
|
6天前
|
SQL 关系型数据库 MySQL
mysql5.7 慢查询配置 查看sql语句执行时间
mysql5.7 慢查询配置 查看sql语句执行时间
28 1
|
6天前
|
SQL 关系型数据库 MySQL
MySQL SQL性能分析 慢查询日志、explain使用
MySQL SQL性能分析 慢查询日志、explain使用
124 0
|
SQL 监控 关系型数据库
你的哪些SQL慢?看看MySQL慢查询日志吧
你的哪些SQL慢?看看MySQL慢查询日志吧
255 0
你的哪些SQL慢?看看MySQL慢查询日志吧
|
SQL 数据可视化 关系型数据库
慢查询定位具体 SQL 语句|学习笔记
快速学习慢查询定位具体 SQL 语句
348 0
慢查询定位具体 SQL 语句|学习笔记
|
SQL Oracle 关系型数据库
|
SQL 存储 算法
|
SQL 关系型数据库 MySQL
SQL慢查询与优化
MySQL的慢查询,全名慢查询日志,是MySQL提供的一种日志记录,用来记录在MySQL中应时间超过阈值的语句。
SQL慢查询与优化
|
SQL 缓存 Cloud Native
SQL 手册-实用 SQL 语句-SQL限流
为应对突发的数据库请求流量、资源消耗过高的语句访问以及SQL访问模型的变化等问题,PolarDB-X 1.0提供了节点级别的SQL限流功能来限制造成上述问题的SQL执行,从而保证实例的持续稳定运行。本文介绍如何使用SQL限流功能。
233 0