总结:SQL查询变慢,常见原因分析!

文章目录

  • 引言
  • SQL查询慢原因
  • 索引失效
    • 特殊情况-执行计划中,key有值,还是很慢怎么办?
  • 多表JOIN
    • 为什么互联网公司都不建议使用多表join?
  • 索引基数太小不合理
  • 查询字段太多
  • 表中数据量太大
  • 数据库连接数不够
  • 为什么乐观锁还会导致大量的锁耗时呢?
  • 数据库表结构不合理
  • 数据库IO或者CPU比较高
  • 存在长事务
  • 锁竞争导致的等待
  • 数据库参数不合理

引言

在面试中,SQL调优是一个常见的问题,通过这个问题可以考察应聘者对于提升SQL性能的理解和掌握程度。通常来说,SQL调优需要按照以下步骤展开。

首先,需要发现问题。最好结合具体业务情况,比如某次线下报警显示出现了慢SQL,或者接口响应时间较长,经过性能分析发现问题出现在SQL查询上。无论何种情况,都要有一个背景故事。

一旦问题被确定,就需要进行问题分析了。接着首先要定位具体的SQL语句,这可以通过各种监控工具或平台来实现。一旦定位到SQL语句,就能知道是哪张表、哪个SQL语句在拖慢性能。

SQL查询慢原因

1、索引失效
2、多表连接
3、查询字段过多
4、数据量过大
5、索引字段基数太小
6、数据库连接不足
7、数据库表结构不合理
8、数据库IO或CPU负载高
9、数据库参数设置不合理
10、长时间事务
11、锁竞争导致的等待

索引失效

首先,当遇到索引失效的问题时,我们通常会通过执行计划来分析数据库查询是否有效地利用了索引。执行计划可以告诉我们查询是如何执行的,是否使用了索引以及索引的效率如何。如果发现查询没有使用索引或者索引效率低下,可能是因为索引设计不合理或者数据分布不均匀导致索引失效。在这种情况下,我们可以考虑优化索引设计,重新构建索引,或者调整SQL查询语句以更好地利用索引。有时候,我们也可以通过强制指定特定的索引来引导查询优化器选择正确的索引。除了修改索引和SQL语句,还可以考虑优化查询条件,避免使用通配符开头的LIKE语句,尽量避免在WHERE子句中对字段进行函数操作,以及尽量减少JOIN操作的复杂度。这些方法都可以帮助提高查询性能和优化索引使用。如果遇到索引失效问题,还可以考虑使用数据库提供的工具和分析功能来进一步诊断和解决问题。

特殊情况-执行计划中,key有值,还是很慢怎么办?

这是在实际中遇到的一种情况。我相信大家或多或少也是遇到过这种情况的。

在执行计划中,当看到key字段有值且type为index时,很多人错误地认为这表示查询已经利用了索引。当我们查看一个SQL查询的执行计划时,经常会遇到类似以下的情况:

这个执行计划中,type=index,key=email_index 很多人会认为这表示这条SQL走了索引,但是其实这么理解是不对的。

如果是走了索引Extra中的内容应该是Using index 而不是Using where; Using index

以上的这个执行计划表明,这个SQL确实用到了email_index的这个索引树,但是他并没有直接通过索引进行匹配或者范围查询,而是扫描了整颗索引树。

所以,type=index 意味着进行了全索引扫描, 会遍历索引树来查找匹配的行,这个效率比扫表扫描快一些,但是很有限,和我们通常意义上理解的走了索引 是两回事儿。

遇到这种情况,大概率是因为没有遵守最左前缀匹配导致的索引失效了。所以需要调整查询语句,或者修改索引来解决。


多表JOIN

在SQL查询中,多表连接是导致执行速度变慢的常见原因之一。当我们需要从多个表中检索数据并将它们组合在一起时,就会使用多表连接。然而,如果不加以优化,这种连接可能会导致查询性能下降。

多表连接的执行速度变慢主要是因为数据库系统需要同时处理多个表,进行数据匹配和组合。这可能涉及大量的数据扫描、比较和排序,导致查询变得缓慢。

为了解决多表连接导致的性能问题,我们可以采取一些优化措施:

1、优化查询条件:确保在连接表时使用有效的查询条件,限制返回的数据量。这可以减少不必要的数据匹配,提高查询效率。
2、合理使用索引:为连接字段创建索引,这样可以加快数据匹配的速度。索引可以帮助数据库系统快速定位需要匹配的数据。
3、限制返回字段:只选择需要的字段,避免返回过多的数据。减少返回字段的数量可以降低数据传输和处理的负担。
4、考虑表的大小和结构:在设计数据库表结构时,考虑到表的大小和关系,可以更好地优化多表连接的性能。
5、使用适当的连接类型:根据查询需求选择合适的连接类型,如INNER JOIN、LEFT JOIN、RIGHT JOIN等。不同的连接类型会影响查询的结果和性能。

举个例子,假设我们有两个表:users和orders,我们想要查询用户及其对应的订单信息。如果我们使用以下SQL查询:

SELECT users.name, orders.order_id
FROM users
JOIN orders ON users.user_id = orders.user_id;

在这个查询中,我们通过user_id字段将users表和orders表连接起来,但如果这两个表的数据量很大,且没有合适的索引,查询可能会变得很慢。通过优化查询条件、添加索引、限制返回字段等方式,可以改善这个查询的性能,使其执行更加高效。


为什么互联网公司都不建议使用多表join?

在SQL查询中,使用JOIN操作可能会导致效率较低的主要原因在于其实现方式

MySQL通常使用嵌套循环(Nested-Loop Join)来执行关联查询。简单来说,这意味着要通过两层循环来比较两个表的记录,外循环遍历第一个表,内循环遍历第二个表,然后逐条比较记录,符合条件的结果被输出。

具体到算法实现上,MySQL主要采用了三种方式:简单嵌套循环(Simple Nested Loop)、块嵌套循环(Block Nested Loop)和索引嵌套循环(Index Nested Loop)。然而,这三种方式的效率都不是特别高。

在实际应用中,如果有两个表进行JOIN操作,复杂度最高可以达到O(n^2) 而对于三个表则是O(n^3),随着表的数量和数据量的增加,JOIN操作的效率会呈指数级下降。

值得一提的是,在MySQL 8.0中引入了哈希连接(Hash Join)算法,这种算法可以提高JOIN操作的效率。哈希连接通过构建哈希表来快速查找匹配的记录,相比于嵌套循环,可以更有效地处理JOIN操作,提升查询性能。

因此,尽管JOIN操作在处理多表关联查询时很常见,但需要注意其效率问题。为了优化查询性能,可以考虑使用适当的索引、优化查询条件、限制返回字段数量,以及利用新的算法如哈希连接来改善JOIN操作的效率。


索引基数太小不合理

什么时字段基数?

举个例子,有一个字段它一共在10万行数据里有10万个值对吧?结果呢?这个10万值,要不然就是0,要不然就是1,那么他的基数就是2,为什么?因为这个字段的值就俩选择,0和1。假设你要是针对上面说的这种字段建立索引的话,那就还不如全表扫描了,因为你的索引树里就仅仅包含0和1两种值,根本没法进行快速的二分查找,也根本就没有太大的意义了,所以这种时候,选用这种基数很低的字段放索引里意义就不大了。


查询字段太多

在数据库查询中,查询字段过多通常是因为我们错误地使用了SELECT *,导致返回了所有字段的数据。一般来说,如果查询字段少于100个,通常不会造成太大问题,除非字段数量非常庞大。在这种情况下,我们可以采取两种方法来解决。

首先,避免查询那些不必要的字段,只选择需要的少部分字段进行查询。这样可以减少数据传输和处理的负担,提高查询效率。

其次,可以考虑进行分表,即垂直分表,将数据拆分到多个表中。通过这种方式,可以将数据分散存储在不同的表中,降低单张表的数据量,提升查询性能。然而,需要注意的是,分表可能会引入多表JOIN的问题,因此在进行拆分时需要考虑数据冗余的情况。

所以,对于查询字段过多的情况,除了避免不必要字段的查询外,还可以考虑通过垂直分表的方式来优化数据存储和查询性能。在拆分表时,需谨慎考虑数据冗余和可能引发的多表JOIN问题,以达到更高效的数据查询和处理。


表中数据量太大

当单个表中的数据量超过1000万条时,通常会导致查询效率下降,即使使用了索引也可能变得比较缓慢。在这种情况下,单纯建立索引并不能完全解决问题。因此,针对大数据量表的情况,可以考虑以下几种解决方案:

1、数据归档:将历史数据移出主表,保留只保留最近半年的数据,而将半年前的数据进行归档。这样可以减少单表数据量,提升查询效率。
2、分库分表、分区:将数据拆分到多个库、多个表或者进行分区存储。通过分散数据存储的方式,可以有效降低单表数据量,提高查询性能。
3、使用第三方数据库:将数据同步到支持大规模查询的分布式数据库中,例如OceanBase、TiDB,或者存储到搜索引擎中,如Elasticsearch等。这些数据库具有更好的扩展性和处理大数据量的能力,可以提升查询效率和系统性能。

所以,针对表中数据量过大的情况,除了建立索引外,还可以通过数据归档、分库分表、分区和使用第三方数据库等方式来优化数据存储和查询性能,以应对大数据量带来的查询效率问题。


数据库连接数不够

当数据库连接数不足时,需要具体分析造成这种情况的原因。可能的原因有几个:

1、业务量过大:如果业务量巨大,单个数据库无法承载,那么最好的解决方案是进行数据库分库操作,将数据分散存储在多个库中,以减轻单库压力。
2、慢SQL或长事务:存在一些慢SQL查询或长时间运行的事务,会占用数据库连接资源,导致数据库连接数不足。这种情况下,慢SQL会占用连接资源,导致其他查询被阻塞,进而影响整体查询效率。


为什么乐观锁还会导致大量的锁耗时呢?

虽然乐观锁是不需要加锁的,通过CAS的方式进行无锁并发控制进行更新的。但是InnoDB的update语句是要加锁的。当并发冲突比较大,发生热点更新的时候,多个update语句就会排队获取锁。

而这个排队的过程就会占用数据库链接,一旦排队的事务比较多的时候,就会导致数据库连接被耗尽。

当数据库连接被耗尽时,通常是因为排队的事务过多导致的。在高并发情况下,如果排队的事务数量很大,就会耗尽数据库连接资源。

这类问题的解决思路有以下几个:
1、使用缓存进行热点数据更新,如Redis,以减轻数据库压力。
2、采用异步更新的方式,平滑处理高并发更新请求,避免峰值冲击。
3、将热点数据拆分存储到不同的库或表中,减少并发冲突。
4、合并更新请求,通过批量执行的方式降低冲突。例如,将多个增加积分的操作合并为一次性批量执行,减少数据库负担。

需要注意的是,第2和第4种方案会引入一定的延迟,将实时更新变为异步更新,可能会影响数据的实时性。而第1和第3种方案在实施过程中成本较高,但相对更完整。

根据实际业务场景,选择合适的解决方案非常重要。在某些情况下,如我们的业务场景,选择第4种方案,即合并更新操作并批量执行,可以有效降低数据库连接压力。举例来说,如果需要给100个用户增加积分,可以将这些操作合并并在一定时间间隔内批量执行,以减少数据库负担。


数据库表结构不合理

当数据库表结构不合理时,这也是造成性能问题的关键原因之一。例如,某些字段存储了过长的内容,或者缺乏合理的冗余导致需要频繁进行多表关联查询。解决这类问题的思路通常是进行数据库重构或者考虑分表操作。


数据库IO或者CPU比较高

另外,数据库高IO或CPU占用率也是常见的问题。当数据库整体IO或CPU负载过高时,查询速度可能会下降,因此需要分析背后的原因并采取相应的解决方案。


存在长事务

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


锁竞争导致的等待

在数据库中,锁竞争也会导致等待。当多个并发请求争夺共享资源时,会导致锁等待,进而增加执行时间,使SQL变慢。这种情况也会类似于CPU被打满的问题。


数据库参数不合理

针对具体业务场景,适当调整数据库参数可以显著提升SQL效率。例如,调整内存大小、缓存大小、线程池大小等参数都可能对数据库性能产生影响。

编辑:三两肉
来源:码上遇见你

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

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

相关文章

Linux操作系统与windows无法相互复制问题

请先看完此文在进行操作!!! 对于无法复制我们逐层分析: 1.为什么无法复制是不是少了什么工具(open-vm-tools-destop) 上网查阅可以看到如下 2.在此之前我的虚拟机装完Ubuntu 16.04的linux系统无法进行apt update(参考一下) li…

【ARM】MDK-Flex服务管理软件使用说明

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 记录MDK网络版部署工具Imtools.exe 的各个界面中相关配置的功能说明 2、 问题场景 解决客户咨询,该服务管理软件如何使用,为客户使用服务管理软件后期自行维护增加一定指导作用。 3、软硬件环…

JCO发表加州大学团队最新医学AI研究,从常规HE染色切片预测同源重组缺陷和铂类药物反应|顶刊精析·24-10-18

小罗碎碎念 这篇文章是关于一项名为DeepHRD的深度学习平台的研究,该平台能够从常规的苏木精-伊红(H&E)染色组织切片中预测同源重组缺陷(HRD)和铂类药物反应。 作者角色姓名单位第一作者Erik N. Bergstrom加州大学圣…

RTThread-Nano学习二-RT-Thread启动流程

一、简介 上一章,我们已经了解了如何通过MDK来移植RTT,不熟悉的可以看如下链接:RTThread-Nano学习一-基于MDK移植-CSDN博客本章我们就来继续了解一下,RTT的启动流程。 二、启动流程 官方给了一幅非常清晰的启动流程图&am…

【尚跑】2024咸阳高新区半程马拉松赛141完赛,时隔一年终于pb,天时地利人和的结果

1、赛事背景 10月13日上午8点30分,“追梦一体化 奔跑再出发”2024咸阳高新半程马拉松赛在创业广场鸣枪开跑,来自全国各地5000名马拉松爱好者汇聚于此,一同奔跑。 谢宇航以1:12:32的成绩,获得男子半程马拉松冠军。李兴焯、李瑜分别…

L9110H电机驱动模块使用指南

接上电后(5V),以MOTOR B为例 如果使得 B-1A 1 B-2A 0 即B-1A端为5V,B-2A端为0V

Elasticsearch是做什么的?

初识elasticsearch 官方网站:Elasticsearch:官方分布式搜索和分析引擎 | Elastic Elasticsearch是做什么的? Elasticsearch 是一个分布式搜索和分析引擎,专门用于处理大规模数据的实时搜索、分析和存储。它基于 Apache Lucene …

spring boot 3.3.4 网关(gateway) 集成knife4j 4.4.0

spring boot版本 3.3.4&#xff0c;jdk 22&#xff0c; springcloud 2023.0.3 官方参考链接 Spring Cloud Gateway网关聚合 | Knife4j (xiaominfo.com) springboot版本信息 <properties> <java.version>22</java.version> <spring-cloud.version>2023…

软件企业选择第三方软件检测机构有哪些好处?

在软件开发的当今时代&#xff0c;确保软件的质量和性能是每个企业面临的挑战&#xff0c;因此软件检测公正必不可少。随着市场的需求&#xff0c;越来越多企业会选择将该项工作交由第三方软件检测机构进行。第三方软件检测机构指独立于软件开发方和需求方的第三方机构&#xf…

Java基于SSM微信小程序物流仓库管理系统设计与实现(源码+lw+数据库+讲解等)

选题背景 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

EMCMO--多任务优化求解约束多目标问题

EMCMO–多任务优化求解约束多目标问题 title&#xff1a; An Evolutionary Multitasking Optimization Framework for Constrained Multi-objective Optimization Problems author&#xff1a; Kangjia Qiao, Kunjie Yu, BoyangQu, Jing Liang, Hui Song, and Caitong Yue. …

C++基础补充(03)C++20 的 std::format 函数

文章目录 1. 使用C20 std::format2. 基本用法3. 格式说明 1. 使用C20 std::format 需要将VisualStudio默认的标准修改为C20 菜单“项目”-“项目属性”&#xff0c;打开如下对话框 代码中加入头文件 2. 基本用法 通过占位符{}制定格式化的位置&#xff0c;后面传入变量 #…

rk3588 opencv 的使用

-------------------------------------------------------------------------------------------------------- 目前是 3588 上无法 直接编译出 C程序。 报错如下&#xff1a; -----------------------------------------------------------------------------------------…

82.【C语言】数据结构之顺序表的初始化和销毁

目录 1.线性表 2.分类 1.静态顺序表&#xff1a;使用定长数组存储元素 代码示例(写入Seqlist.h中) 2.动态顺序表:使用与动态内存管理有关的函数 代码示例(写入Seqlist.h中) 补:数据管理的四个需求:增改删查 3.操作顺序表 1.初始化顺序表 1.不开辟空间 2.开辟空间 1…

无人机之三维航迹规划篇

一、基本原理 飞行环境建模&#xff1a;在三维航迹规划中&#xff0c;首先需要对飞行环境进行建模。这包括对地形、障碍物、气象等因素进行准确的测量和分析&#xff0c;以获得可行的飞行路径。 飞行任务需求分析&#xff1a;根据无人机的任务需求&#xff0c;确定航迹规划的…

分布式篇(分布式事务)(持续更新迭代)

一、事务 1. 什么是事务 2. 事务目的 3. 事务的流程 4. 事务四大特性 原子性&#xff08;Atomicity&#xff09; 一致性&#xff08;Consistency&#xff09; 持久性&#xff08;Durability&#xff09; 隔离性&#xff08;Isolation&#xff09; 5. MySQL VS Oracle …

汇总10个AI免费一键生成PPT的网站

一、前言 PPT幻灯片是现代办公和学习中的重要组成部分。它在工作、研究或培训中扮演着重要角色&#xff0c;并能够让观众更好地理解信息。随着当今人工智能技术的快速发展&#xff0c;现在有很多免费的AI PPT生成器可供选择&#xff0c;帮助用户更加便捷地制作出高效且具有较强…

基于SpringBoot+Vue+uniapp微信小程序的宿舍报修系统的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

Qt获取磁盘信息+表格显示

效果展示 主要代码 获取磁盘相关数据 获取磁盘数据 Qt 没有提供相关的接口&#xff0c;需要使用 Windows API。接口解释如下&#xff1a; BOOL GetDiskFreeSpaceExW([in, optional] LPCWSTR lpDirectoryName,[out, optional] PULARGE_INTEGER lpFreeBytesAvailable…

GPIO口的学习

推挽输出 用它去控制一个mos管&#xff0c;当输出高电平时电流这样流出去&#xff0c;给外面的这颗mos管的栅极充电&#xff0c;所以这个过程称为推把电流推出去 然后当IO口输出低电平时电流这样流进来,给外面的这颗mos管的栅极放电,那这就是挽&#xff0c;把电流挽回来,所以所…