提升SQL查询效率的终极指南

在面试中,SQL 调优经常是被问及的问题,它可以考察候选人对于 SQL 整体性能优化的理解和掌握程度。一般来说,SQL 调优的步骤可以从以下几个方面入手。

首先,需要准确地定位问题。在面试中,最好能结合具体的业务场景进行说明,例如某次线下报警引发的慢 SQL 问题,或者性能分析显示接口响应时间过长,根源是 SQL 查询效率不佳。无论何种情况,都需要提供背景信息。

一旦问题定位清楚,接下来就是对问题进行深入分析。

首先,需要通过各类监控平台或工具准确定位到具体的 SQL 语句。一旦定位到了问题 SQL 语句,我们就能够确定是哪张表或哪个 SQL 语句执行速度较慢。

接下来,需要进行详细的分析。一般而言,一个 SQL 语句执行缓慢可能有以下几种原因:

  1. 索引未被有效利用
  2. 多表连接
  3. 查询字段过多
  4. 数据量过大的表
  5. 索引的区分度不高
  6. 数据库连接数不足
  7. 数据库表结构不合理
  8. 数据库的 IO 或 CPU 负载过高
  9. 数据库参数设置不合理
  10. 长时间事务
  11. 锁竞争引起的等待

因此,进行一次全面的 SQL 调优时,通常需要考虑上述几个因素,往往会涉及其中一个或多个问题。接下来,需要逐一进行优化。

首先,处理索引失效的问题通常要通过执行计划分析是否正确使用了索引,以及使用的索引是否符合预期。如果索引设计不合理或者因索引失效导致问题,可以考虑调整索引设计,修改 SQL 语句,或者强制使用特定的索引。索引失效可参考历史文章:

一篇文章聊透索引失效有哪些情况及如何解决

其次,多表连接(join)也是导致 SQL 执行速度较慢的常见原因之一。关于这个夺标 JOIN 是怎么实现的,我在以下文章中详细阐述了:

MySQL 的 JOIN 到底是怎么玩的

接下来,如果是索引区分度不高的话,这个其实也和索引不合理有关,但是其实到底快不快,用不用索引,并不是因为区分度高不高导致,其实还是索引扫描的行数的成本导致。所以,有的时候不能认为区分度不高就一定会效率低,或者一定就不适合创建索引。

查询字段过多有时是因为误用了 SELECT *,通常情况下,查询少于 100 个字段并不是大问题,除非字段数目极多。解决方法有两种:一是只查询必要的字段,避免检索不需要的数据;二是进行垂直分表,将数据分散存储到多张表中。然而,这种分散存储也可能带来需要多表连接的问题,因此在进行分表时需要考虑数据冗余的问题。
对于表中数据量过大的情况,一般而言,超过 1000 万条数据会显著降低查询效率,即使使用了索引也可能不够快。因此,解决方法包括:

  1. 数据归档,将历史数据移出,只保留近期数据,例如保留最近半年数据,将半年前的数据归档。
  2. 分库分表或分区。通过拆分数据来分散存储,以减轻单表的压力。具体的分库分表和分区策略可以参考详细文档,这里不展开说明。
  3. 考虑使用支持大数据量查询的第三方数据库,如 OceanBase、TiDB,或者搜索引擎如 Elasticsearch 等。

数据库连接数不足也需要具体分析原因。可能原因包括:业务量过大,单个数据库无法处理;存在慢 SQL 或长事务导致连接阻塞,进而影响其他查询速度。

数据库表结构不合理通常是一个关键原因。例如,某些字段可能存储了过长的内容,或者没有进行合理的数据冗余,导致需要频繁进行多表关联查询等情况。解决方法通常是进行数据库结构重构或者进行表的分解。

数据库的 IO 或 CPU 负载较高也是常见问题。当数据库整体的 IO 或 CPU 负载升高时,查询速度可能会受到影响。因此,需要深入分析其背后的原因,并采取相应的解决策略。关于 CPU 相关知识点可以参考:

聊聊性能指标 CPU 利用率如何计算的?

「性能指标」CPU 飙高排查实战

存在长事务和慢 SQL 类似,都会占用数据库连接,从而导致其他请求需要等待。

锁竞争导致的等待则是在高并发情况下,多个请求竞争共享资源,导致锁定等待时间增长,进而使得 SQL 执行变慢。这一过程也可以参考上述导致 CPU 负载过高的问题。

数据库参数设置不合理也是常见问题,针对具体的业务场景进行适当的参数调整,有时能显著提升 SQL 的效率。例如调整内存大小、缓存大小以及线程池大小等。

扩展知识

参数优化

假设我们管理的数据库名为 mydb,其中包含一个名为 mytable 的 InnoDB 表。该表具有自增主键 id,一个整数类型的 age 字段和一个字符串类型的 name 字段。我们希望对这个表进行优化。

首先,可以通过执行 SHOW VARIABLES LIKE 'innodb%'; 命令来查看当前 InnoDB 参数的设置情况。这些参数涵盖了缓冲池大小、刷新间隔、日志大小等核心设置。

接下来,我们可以尝试调整几个关键参数来优化数据库的性能:

innodb_buffer_pool_size:缓冲池大小是 InnoDB 存储引擎的关键参数之一,它决定了 InnoDB 存储引擎在内存中使用的大小。通常建议将该参数设置为系统可用内存的 70% 到 80%。例如,如果系统总内存为 8GB,我们可以将 innodb_buffer_pool_size 设置为 6GB。在 MySQL 中,可以使用以下命令进行设置:


SET GLOBAL innodb_buffer_pool_size=6G;

**innodb_read_io_threads innodb_write_io_threads **这两个参数控制着 InnoDB 存储引擎的 I/O 线程数量。一般建议将它们设置为可用 CPU 核心数的一半。在 MySQL 中,您可以使用以下命令进行设置:

SET GLOBAL innodb_read_io_threads=4;
SET GLOBAL innodb_write_io_threads=4;

innodb_log_file_size 参数控制着事务日志文件的大小。默认情况下,其大小为 5M,这通常是不足够的。在 MySQL 中,您可以使用以下命令进行设置:

SET GLOBAL innodb_log_file_size=1G;

一般来说,在设置这个参数之前,需要先进行数据采样。可以观察业务高峰期约 2 小时内写入的日志量,然后将这个量作为设定事务日志文件大小的参考。通常建议设置为约 1G 左右,或者系统内存的 1/4。

区分度不高的字段建索引一定没用吗

关于刚刚上面提到的区分度不高的字段。做一下解释,这个区分度不高的字段建立索引到底有没有用呢。

答案是:不一定。

在某些情况下,索引的有效性并不完全取决于字段的区分度。例如,如果一个表中包含性别字段,仅有两个可能的取值:男和女,那么通常情况下这个字段的区分度较低,使用该字段进行查询可能无法有效地过滤大量数据,从而无法充分发挥索引的优势。

然而,也存在特殊情况。比如,如果性别的分布比例是 95%男性和 5%女性,那么当以"女"作为性别查询条件时,依然可以通过索引进行高效查询,因为它能够快速过滤掉大部分数据,从而提升性能。这种情况下,索引仍然能够显著提升效率。

类似的情况在任务表中也很常见。例如,任务表中可能有一个状态字段,大多数任务处于成功状态(SUCCESS),只有少数任务处于初始化状态(INIT)。在这种情况下,为状态字段添加索引可以显著提升查询效率。这样在扫描任务表并执行任务时,可以更快地定位到需要处理的任务。

因此,虽然字段的区分度影响索引的效果,但在特定的数据分布情况下,即使区分度不高的字段仍然可以通过索引来优化查询性能。

如有问题,欢迎微信搜索【码上遇见你】。

免费的Chat GPT可微信搜索【AI贝塔】进行体验,无限使用。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/44034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【组件库】element-plus组件库

文章目录 0. 启动项目1. gc.sh 新增组件2. 本地验证(组件注册的方式)3. 官方文档修改3-1. 左侧菜单3-2 . 配置md文档3-3. 代码问题:文档修改----------------------------------------------4. 将naiveui的split 分割组件【 复制、迁移】到 element-ui-plus组件库4.1 naiveu…

三级_网络技术_11_路由设计技术基础

1.以下协议中不属于内部网关协议的是()。 RIP OSPF BGP IGRP 2.下列关于路由协议的描述中,错误的是()。 RIP协议中,路由器在接收到更新报文后按照最短路径原则更新路由表 RIP协议中,要求路由器周期性的向外发送路由刷新报文 OSPF协议…

linux:命令执行过程【图表】

命令执行过程 步骤描述详细信息1启动终端在CentOS系统上打开终端窗口。可以通过快捷键 Ctrl Alt T 或在图形界面中找到并启动终端应用程序。2输入命令在终端中输入命令,如 ls -l,然后按下回车键。3Shell接收命令Shell(如bash)…

关于向日葵的P5旁路由

日常生活需要内网穿透的时候越来越多,买了两台P5,p2p 传输 时间延时在 20ms 左右,相当好用 现在的路由器添加静态路由之类的,得开启开发者模式 [ 官方手册中给了,双旁路的用法 (企业级部署)] 如果是个人,可以在常用的服务器上设置静态路由,不用非得在 内网的主要路由器中设置静…

FastReport 指定sql,修改数据源 ( 非DataSet修改 )

FastReport 指定sql,修改数据源,非DataSet修改 介绍报告文件: codetest.frx 文件核心代码:(扩展)小结一下: 介绍 在FastReport中,经常会遇到需要给 sql 加条件的情况。 &#xff0…

爆破器材期刊

《爆破器材》简介   《爆破器材》自1958年创刊以来,深受广大读者喜爱,是中国兵工学会主办的中央级技术刊物,在国内外公开发行,近几年已发行到10个国家和地区。《爆破器材》杂志被美国著名检索机构《化学文摘》(CA&a…

相机光学(二十九)——显色指数(Ra)

显指Ra是衡量光源显色性的数值,表示光源对物体颜色的还原能力。显色性是指光源对物体颜色的呈现能力,即光源照射在同一颜色的物体上时,所呈现的颜色特性。通常用显色指数(CRI)来表示光源的显色性,而显指Ra是…

c# 基础习题答案 20240709

一、实现一个冒泡排序函数 using System;public class Program {public static void Main(){int[] arr { 22,11,33 };BubbleSort(arr);foreach (var item in arr){Console.Write(item " ");}Console.WriteLine();}// 冒泡排序函数public static void BubbleSort(i…

XTuner 微调 LLM:1.8B, 部署

扫码立刻参与白嫖A100,书生大模型微调部署学习活动。亲测有效 内容来源:Tutorial/xtuner/personal_assistant_document.md at camp2 InternLM/Tutorial GitHubLLM Tutorial. Contribute to InternLM/Tutorial development by creating an account on G…

从零手写实现 nginx-26-rewrite url 重写

前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …

设计无缝体验:交互设计流程全解析

完整的产品交互设计流程是什么?完整的产品交互设计流程包括研究用户需求、指定信息架构、制作产品原型、进行用户测试和实时发布产品。交互设计就是从人与产品之间的关系入手,通过产品设计来满足大众的日常需求。随着网络技术的流行,产品交互…

工业机床CNC设备如何上云?

工业机床CNC设备如何上云? 工业机床的计算机数控(CNC)设备实现远程监控数据上云,是现代制造业智能化转型的关键一环。这一过程不仅能够实时监测设备状态、优化生产流程,还能通过大数据分析提升生产效率与产品质量&…

Java包装类简单认识泛型

1 包装类 在 Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, Java 给每个基本类型都对应了 一个包装类型。 例如我们之前的基本数据类型和包装类。 1. 装箱和拆箱 2.自动装箱和自动拆箱 2.泛型 1.什么是泛型 …

【C++项目】从零实现一个在线编译器

前言 身为一名程序员,想必大家都有接触过像leetcode这样的刷题网站,不知你们在刷题的过程中是否思考过一个问题:它们是如何实现在线编译运行的功能。如果你对此感到好奇,那么本文将一步步带你来实现一个简易在线编译器。 项目概…

vue3+antdv仿百度网盘样式文件夹管理组件

实现: 默认进入页面时,文件夹全选;文件夹状态,以及文件夹内的文件选择状态,与组件联动文件夹数量,根据后端数据动态生成 实现思路: 将后端数据存到vuex中,增加(多选框…

学懂C#编程:C# 索引器(Indexer)的概念及用法

C#中的索引器(Indexer)是一种特殊的成员,它允许类或结构的实例像数组那样通过索引来访问其内部的数据。索引器提供了一种灵活的方式来暴露集合或数组类型的内部数据,使得客户端代码可以使用类似于数组下标的语法来访问类的成员&am…

LAMP万字详解(概念、构建步骤)

目录 LAMP Apache 起源 主要特点 软件版本 编译安装httpd服务器 编译安装的优点 操作步骤 准备工作 编译 安装 优化执行路径 添加服务 守护进程 配置httpd 查看 Web 站点的访问情况 虚拟主机 类型 部署基于域名的虚拟主机 为虚拟主机提供域名解析&#xff…

机器人三定律及伦理分析

全世界的机器人定律并没有一个统一的标准或体系,但是在科学文献中,最广为人知的是由科幻小说家阿西莫夫提出的“机器人三定律”。本文将以这些定律为基础,分析现有的机器人伦理和实际应用中的问题,给出若干实例,并对相…

[Flutter] Android Studio pub get 不起作用

前情:在文件中将webview_flutter: ^4.7.0改为webview_flutter: ^4.8.0,又改回webview_flutter: ^4.7.0,发现本地库的版本一直是8,pub get怎么都不起作用(只对webview_flutter不起作用,其他的都更新了&#…

EPSON LQ80KF II驱动 打印机 0x00000003e3

1.添加打印机 2.按名次选择共享打印机,输入共享打印机ip 3.选择创建新端口 4.选择打印机驱动