【MySQL】常见的SQL优化方式(二)

news2024/12/27 17:15:55

目录

1、limit 优化

(1)延迟关联(索引覆盖+子查询)

(2) 已知位置查询

2、group by 优化

(1)使用索引

(2)避免排序

(3)分析查询

3、count 优化

(1)常见的几种 COUNT() 用法及其效率对比

(2)性能排序

4、update 优化

(1)举例说明

(2)优化建议

1、limit 优化

        当使用 LIMIT 进行大数据量分页时,比如 LIMIT 2000000, 10,MySQL 需要先从头开始排序并扫描前 2000010 条记录,但实际上我们只关心从第 2000000 到 2000010 的 10 条数据。这种操作的代价非常高,因为它需要 MySQL 扫描大量不必要的行,浪费了很多时间和资源。

(1)延迟关联(索引覆盖+子查询)

        使用索引覆盖:首先,通过查询一个较小的字段(比如主键 ID),快速得到所需的 ID 列表。因为查询主键或索引列时可以直接从索引中返回,不需要访问全表数据,速度快很多。

        子查询(或者JOIN)再获取完整数据:拿到 ID 列表之后,再通过 IN 子查询或 JOIN 来查询完整的数据行。这一步只查询所需的几条记录,而不是像之前那样扫描大量无关的数据。

#1、利用索引,先获取需要的主键 ID
SELECT id FROM tb_sku ORDER BY id LIMIT 2000000, 10;
#2、通过子查询,查询这些 ID 对应的完整记录
EXPLAIN SELECT * FROM tb_sku t, 
    (SELECT id FROM tb_sku ORDER BY id LIMIT 2000000,10) a 
WHERE t.id = a.id;

(2) 已知位置查询

        如果有一个单调递增的主键,我们可以利用这个特性来避免使用 OFFSET。比如我们知道上一页的最后一条记录的 id 是 16030,那么下一页可以直接从 id = 16030 开始查

SELECT * FROM tb_sku WHERE id > 16030 LIMIT 10;

        所以,偏移量大的时候LIMIT 查询可能会很慢。为了优化,可以借助延迟查询或者已知位置查询,这两种方式可以减少不必要的记录扫描,提升查询效率。

2、group by 优化

        在写 SQL 查询时,GROUP BY 是我们经常用来对数据进行分组的操作,但它也容易成为性能的瓶颈,那怎样才可以让分组操作更快呢?

(1)使用索引

        分组操作时,使用索引可以大幅提高效率。数据库通过索引可以快速定位到需要的数据,而不用去扫描整个表。和其他查询一样,GROUP BY 也遵循最左前缀法则,意思是如果我们用多个字段来分组,数据库只会使用最左边的字段上的索引来加速操作。所以,如果我们在 GROUP BY 中使用的字段是有索引的,并且顺序和索引的定义一致,就能提升查询效率。

# 执行分组操作,根据 profession 字段分组
EXPLAIN SELECT profession, COUNT(*) 
FROM tb_user 
GROUP BY profession;

# 创建新的联合索引
CREATE INDEX idx_user_pro_age_sta ON tb_user(profession, age, status);

# 执行分组操作,根据 profession 字段分组
EXPLAIN SELECT profession, COUNT(*) 
FROM tb_user 
GROUP BY profession;

# 执行分组操作,根据 profession 和 age 字段分组
EXPLAIN SELECT profession, COUNT(*) 
FROM tb_user 
GROUP BY profession, age;

(2)避免排序

        GROUP BY 默认会对分组字段进行排序。如果不需要排序,可以通过 ORDER BY NULL 来告诉数据库不需要额外排序,这样可以节省排序的开销。

SELECT profession, COUNT(*)
FROM tb_user
GROUP BY profession
ORDER BY NULL;

(3)分析查询

        想知道 GROUP BY 是否使用了索引?可以用 EXPLAIN 命令查看执行计划,它会告诉我们查询是如何被执行的,是否用到了索引,是否有全表扫描等信息。如果发现索引没用上,那就得考虑调整 GROUP BY 字段的顺序或添加适合的索引了。

EXPLAIN SELECT profession, COUNT(*)
FROM tb_user
GROUP BY profession
idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEtb_userindexidx_user_pro_age_sta10NULL20Using index

分析结果:

  • type:index 表示使用了索引扫描,这意味着查询是基于索引执行的,不再是全表扫描 (ALL),因此性能提升。
  • possible_keys:显示可用的索引,表明查询可以使用 idx_user_pro_age_sta
  • key:实际使用的索引是 idx_user_pro_age_sta,表明查询已经利用了我们创建的联合索引。
  • rows:这里显示的是估计扫描的行数。
  • Extra:Using index 表示查询直接从索引中获取数据,避免回表(从索引到表中的其他列查找),提高了效率。

3、count 优化

        在 MySQL 中,COUNT() 函数经常用于统计行数,但它的效率会根据用法不同而有所差异。MyISAM 和 InnoDB 两种存储引擎在处理 COUNT(*) 时是不同的:

  • MyISAM:它会直接从磁盘读取已经存储的总行数,这样当执行 COUNT(*) 时,如果没有 WHERE 条件,可以直接返回这个数值,效率非常高。
  • InnoDB:它不会像 MyISAM 那样保存行数,而是需要一行行地把数据从引擎中读出来并累加,所以在 InnoDB 中执行 COUNT(*) 的效率相对低一些,尤其当有 WHERE 条件时,每一行都得判断。

(1)常见的几种 COUNT() 用法及其效率对比

COUNT(*)

  • 不取具体的字段值,InnoDB 做了优化,直接按行数累加,效率是最高的。所以在不知道该选哪种写法时,推荐使用 COUNT(*)

COUNT(主键)

  • InnoDB 会遍历整张表,取出每一行的主键,然后返回给服务层,服务层按行累加。主键不会为 NULL,因此每一行都会被计算在内。

COUNT(字段)

  • 如果字段没有 NOT NULL 约束,InnoDB 会一行行把数据取出来,返回给服务层,服务层判断该字段是否为 NULL,非 NULL 才计数。
  • 如果字段有 NOT NULL 约束,那么服务层会直接按行累加,因为字段不可能为 NULL

COUNT(1)

  • InnoDB 遍历表时不取具体字段值,只是简单遍历,服务层给每一行都加一个数字“1”,然后累加。这和 COUNT(*) 差不多,性能几乎一样。

(2)性能排序

按效率从低到高排序:COUNT(字段) < COUNT(主键) < COUNT(1) ≈ COUNT(*)

因此,最优的选择是 COUNT(*),因为它的查询方式被专门优化过,性能最好。

4、update 优化

        在 InnoDB 存储引擎中,行锁是针对索引加的锁,而不是针对记录加的锁。这样设计的好处是提高了并发性能,但前提是要确保使用了有效的索引。若使用的索引失效,行锁会升级为表锁,这会大大降低并发性能。

(1)举例说明

        假设有一个 users 表,包含字段 id(主键索引)和 name(没有索引)。我们有以下两个 UPDATE 语句:

UPDATE users SET age = 30 WHERE id = 1;
  • 在这个语句中,条件 id = 1 是一个索引,因此 InnoDB 只会给 id 为 1 的这一行加锁。这使得其他事务仍然可以并发地访问和修改表中其他行的数据,性能得到优化。
UPDATE users SET age = 30 WHERE name = '韦一笑';
  • 这个语句的条件 name = '韦一笑' 没有索引,因此 InnoDB 会在扫描整个表来查找满足条件的行。此时,由于无法加行锁,行锁将会升级为表锁,整个 users 表会被锁住。这意味着在当前事务未提交之前,其他事务无法对这个表进行任何操作,导致并发性能降低。

(2)优化建议

创建合适的索引:确保更新操作的条件字段有索引,避免不必要的表锁升级。

避免大范围更新:尽量减少更新操作对大范围记录的影响,尤其是在高并发环境下。

 推荐:

【MySQL】常见的SQL优化方式(一)-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/m0_65277261/article/details/142376280?spm=1001.2014.3001.5501【计算机组成原理】存储器知识_计算机组成原理存储器知识点-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/m0_65277261/article/details/134770339?spm=1001.2014.3001.5501

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

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

相关文章

LeetCode[中等] 739. 每日温度

给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 思路 栈 暴力法为遍历列…

毕业论文不会写?教你如何利用AI来帮我完成初稿

AI是个工具&#xff0c;它能帮你提高效率&#xff0c;但可不能完全替代你的工作。所以&#xff0c;你要做的是学会如何利用AI来辅助你的毕业论文写作。 writehelp智能写作辅导&#xff1a;可节约1000小时写作时间帮助快速完成初稿的撰写。 传送门&#xff1a;http://www.write…

Qt Linguist手册-翻译员

翻译人员 Qt Linguist 是为 Qt 应用程序添加翻译的工具。一旦安装了 Qt&#xff0c;就可以像开发主机上的其他应用程序一样启动 Qt Linguist。 Qt Linguist 主窗口包含一个菜单栏和以下视图&#xff1a; 上下文 (F6) 用于从上下文列表中选择要翻译的字符串。字符串 (F7) 用于…

软考中级网络工程师下午题近五年笔记

刷题地址&#xff1a;软考达人—专业的软考刷题题库&#xff0c;软考历年真题&#xff0c;软考模拟考试&#xff0c;软考考前押题。柴丁科技 (ruankaodaren.com) 上面这个网站有的图不清晰&#xff0c;也可以看这个网站策未来网校——在线刷题、智能刷题 (ceweilai.cn) 2019…

[leetcode] 71. 简化路径

文章目录 题目描述解题方法栈java代码复杂度分析 题目描述 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 / 开头&#xff09;&#xff0c;请你将其转化为 更加简洁的规范路径。 在 Unix 风格的文件系统中规则如下&#xff1…

springboot+大数据+基于协同过滤算法的校园食堂订餐系统【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

25:stm32的低功耗模式

低功耗模式 1、PWR电源控制2、低功耗模式 1、PWR电源控制 PWR&#xff08;Power Control&#xff09;电源控制。PWR负责管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压监测器和低功耗模式的功能&#xff0c;这里我们只学习低功耗模式的功能&#xff0c;低功耗模式…

【AI】AIOT简介

随着技术的快速发展&#xff0c;人工智能AI和物联网IoT已经成为当今最热门的技术领域。AIOT是人工智能和物联网的结合&#xff0c;使物联网设备更加智能化&#xff0c;能够进行自主决策和学习的技术。 通过物联网产生、收集来自不同维度的、海量的数据存储于云端、边缘端&#…

Netty源码-业务流程之写数据

Netty基本介绍&#xff0c;参考 Netty与网络编程 1、源码分析&#xff0c;EchoServerHandler之Write流程 1.1 write流程入口 通常我们通过ChannelRead收到消息后&#xff0c;需要给一个响应&#xff0c;通过ctx.write()将响应返回客户端。 在自定义handler的channelRead方法…

极限电流型氧传感器的工作原理以及有哪些应用场景?

极限电流型氧传感器的工作原理&#xff1a; 极限电流型氧传感器的工作原理基于稳定ZrO2固体电解质的氧泵作用。在已稳定化ZrO2两侧被覆铂电极&#xff0c;阴极侧用有气体扩散孔的罩接合&#xff0c;形成阴极空腔。在一定的温度下&#xff0c;当ZrO2电极两侧加一定电压时&#…

使用AOP处理参数

说明&#xff1a;在一些时候&#xff0c;我们需要在接口介绍到参数前处理参数&#xff0c;像参数校验、参数转换等&#xff0c;本文介绍如何使用AOP来实现此需求。 场景 需求&#xff1a;有一批开放给第三方调用的接口&#xff0c;之前传递的都是用户表的ID&#xff0c;现在需…

vscode 内网不联网如何导入vscode插件

如果有小伙伴百度到这篇文章&#xff0c;那一定是遇到了在内网开发不能联网的问题&#xff0c;那就往下看看吧。 安装一个新的Visual Studio Code&#xff0c;需要必要的一些插件&#xff0c;但是不能联网&#xff0c;于是自带的扩展程序安装便不能用了。 1、在一台能访问外网…

Kali Linux入门教程(非常详细)从零基础入门到精通,看完这一篇就够了。

作为一名从事渗透测试的人员&#xff0c;不懂Kali Linux的话&#xff0c;就out了。它预装了数百种享誉盛名的渗透工具&#xff0c;使你可以更轻松地测试、破解以及进行与数字取证相关的任何其他工作。 今天给大家分享一套Kali Linux资料合集&#xff0c;包括12份Kali Linux渗透…

数据结构-栈(理解版)

一、栈的定义 相信大家对于栈或多或少有一些了解&#xff0c;可能大多数人会告诉你栈是一种先进后出的数据结构。这其实说了跟没说一样(❁◡❁)&#xff01;当然&#xff08;last in&#xff0c;first out&#xff09;是栈最有特色的性质。 这里可以给大家一些比较好理解的例…

车辆重识别(改进的去噪扩散概率模型)论文阅读2024/9/29

所谓改进的去噪扩散概率模型主要改进在哪些方面&#xff1a; ①对数似然值的改进 通过对噪声的那个方差和T进行调参&#xff0c;来实现改进。 ②学习 这个参数也就是后验概率的方差。通过数据分析&#xff0c;发现在T非常大的情况下对样本质量几乎没有影响&#xff0c;也就是说…

Python库matplotlib之四

Python库matplotlib之四 小部件(widget)RadioButtons构造器APIs应用实列 Slider构造器APIs应用实列 小部件(widget) 小部件(widget)可与任何GUI后端一起工作。所有这些小部件都要求预定义一个Axes实例&#xff0c;并将其作为第一个参数传递。 Matplotlib不会试图布局这些小部件…

基于Springboot+Vue的c语言学习辅导网站的设计与实现 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…

美洽客户服务AI Agent 1.0,全渠道多场景赋能业务增长

“到 2025 年&#xff0c;由 AI 驱动的客户服务交互将增长 400%。” ——Gartner “70% 的企业报告称&#xff0c;在实施 AI 驱动的客户服务平台后&#xff0c;客户满意度分值提升。” ——麦肯锡 在美洽 AI 中心负责人看来&#xff0c;未来几年&#xff0c;AI 之于企业将由辅助…

国内ChatGPT镜像网站整理汇总【OpenAI o1/GPT 4o】-2024/10月最新

一、中文镜像站 ①yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画、文件上传 ②chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③AI Chat 支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;mirrored site&am…

解决$‘r‘ command not found或者文件夹显示’tvsf 33‘$‘r‘

问题现象: 某客户反馈在执行脚本的时候文件夹显示存在问题,如下图: 但是脚本文件中的内容并没有\r字符,如下图: 也有客户反馈如下: 问题分析: $\r’是回车符的转义表示。在Unix和Linux系统中,回车符是一个不可见的控制字符,它通常用于文本文件中的行结尾。以上…