慢查询优化思路

本文介绍慢查询的优化思路,但不以索引优化作为重点,索引相关的优化可以参考《索引使用原则、索引失效》、《MySQL单表查询时索引使用情况》。

1.应用层面

对于报表类页面,一般涉及到的数据库表较多且数据量大,容易造成接口查询较慢。

如果页面还有分页的要求,一般需要先进行 count,再进行列表查询。在做 count 时可以去查询语句中无关的返回字段,去掉 order by。另外,对于 A left join B 这种情况,实际上 A 表已经包含了完整的数据行数,因此可以简化成仅对表 A 做 count。

2.SQL 层面

2.1in 与 exists 的选择

选择使用 in 还是 exists 的标准是:小表驱动大表

比如下面这样:

select * from A where exists (select cc from B where B.cc=A.cc);
select * from A where cc in (select cc from B);

当 A 小于 B 时,用 exists。因为 exists 的实现,相当于遍历表 A,然后用每一行去表 B 中进行比较判断,实现的逻辑类似于:

# 此时扫描行数为 A + A*BA 的大小对扫描行数影响较大。
for i in Afor j in Bif j.cc = i.cc then ...

当 B 小于 A 时,用 in。因为实现的逻辑类似于:

# 此时扫描行数为 B + B*AB 的大小对扫描行数影响较大。
for i in Bfor j in Aif j.cc = i.cc then ...

因此,哪个表小就用哪个表作为驱动表,A 小就用 exists,B 小就用 in。

2.2避免子查询

执行子查询时,MySQL 需要为内层查询语句(即子查询)的查询结果建立一个临时表 ,然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表 。这样会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。且 MySQL 对子查询的优化并不好,有可能导致全表扫描。

2.3group by 优化

  • group by 使用索引的原则几乎跟 order by 一致 ,group by 即使没有过滤条件用到索引,也可以直接使用索引。
  • group by 先排序再分组,遵照索引建的最佳左前缀法则
  • 当无法使用索引列,增大 max_length_for_sort_data 和 sort_buffer_size 参数的设置
  • where 效率高于 having,能写在 where 限定的条件就不要写 在having 中
  • 减少使用 order by,和业务沟通能不排序就不排序,或将排序放到程序端去做。order by、group by、distinct 这些语句较为耗费CPU,数据库的 CPU 资源是极其宝贵的。
  • 包含了order by、group by、distinct 这些查询的语句都需要排序,如果用不到索引就需要进行 filesort,一般情况下 filesort 较为耗时。因此 where 条件过滤出来的结果集请保持在1000 行以内,否则SQL会比较慢。

2.4分页查询优化

对于下面的查询,仅需要返回 10 条记录,却需要对大量数据进行排序。且由于查询返回的是所有字段,因此优化器很可能会不走索引,导致用 filesort 排序,因此排序的代价非常大。

SELECT * FROM student ORDER BY id LIMIT 200000,10;

优化思路一:在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容

SELECT * FROM student t JOIN (SELECT id FROM student ORDER BY id LIMIT 2000000,10)a
ON t.id = a.id;

优化思路二:该方案适用于主键自增的表,可以把 Limit 查询转换成某个位置的查询 。

SELECT * FROM student WHERE id > 2000000 LIMIT 10;

2.5sql 编写尽量精准

sql 编写尽量精准,像 is 代替 is not、= 代替 <>、人工条件下推、列剪枝、添加 limit 等方式,都能引导优化器生成更高效的执行计划。

下面先介绍 is 代替 is not,其他的待日后补充(我一定会回来的!)。

对于有索引的情况,用 is null 代替 is not null。假设我们有一个学生表 student 和班级表 class,学生表记录了学生的学号 stu_no,而班级表记录了班级信息以及每个班级的班长的学号 monitor_no。现在要找出所有不为班长的学生信息。实现方法如下:

方法一:

select sql_no_cache a.* from student a where a.stu_no not in (select monitor_no from class where monitor_no is not null
)

方法二:

select sql_no_cache a.* from student a left join class b on a.stu_no = b.monitor_no where b.monitor_no is null;

方法二用 join 方式替换了子查询,且通过 b.monitor_no is null 进行过滤,如果 monitor_no 上存在索引,则查询效率会高很多。

用 = 替换 <> 也是类似的道理,此处不再赘述。

3.数据库表层面

除了索引以外,可以考虑对表进行分区、分桶;行存表转列存表等。

4.服务器参数层面

4.1 FileSort 方式排序/分组优化

在 SQL 中尽量使用 Index 完成排序或分组。对于排序,如果 WHERE 和 ORDER BY 后面是相同的列就使用单索引列;

如果不同就使用联合索引。但也存在无法使用 Index 的情况,此时就需要对 FileSort 方式进行调优。

调优策略:

  • 尝试提高 sort_buffer_size,避免需要排序的字段太多导致一次操作完成不了需要多次 IO。
  • 尝试提高 max_length_for_sort_data:由于需要返回的字段长度超出该阈值之后排序算法会从「单路排序」变为「双路排序」,而双路排序需要更多的 IO 次数。
  • Order by 时 select * 是一个大忌。最好只 Query 需要的字段。这和上一点也是相辅相成的。

4.2优化联表查询性能

MySQL 在进行表连接时可采用的嵌套循环连接(Nested-Loop Join)算法有:

  • 索引嵌套循环(Index Nested-Loop Join)
  • 简单嵌套循环(Simple Nested-Loop Join)
  • 块嵌套循环(Block Nested-Loop Join)

其中块嵌套循环需要用到 join buffer 来存储驱动表数据(经过单表条件过滤后的数据,且只包含需要返回的字段),join buffer 越大意味着需要加载驱动表数据的次数越小。因此,如果自己的机器的内存比较大可以尝试调大 join_buffer_size 的值来对连接查询进行优化。

Nested Loop 与 Hash Join 对比:

Hash join 也属于联表查询的一种算法。对于大数据集连接,Hash Join 通常更优;而对于小数据集连接,Nested Loop 可能更合适。选择哪种连接方式取决于具体的数据量和表的特性。

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

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

相关文章

自然语言处理: RAG优化之Embedding模型选型重要依据:mteb/leaderboard榜

本人项目地址大全&#xff1a;Victor94-king/NLP__ManVictor: CSDN of ManVictor git地址&#xff1a;https://github.com/opendatalab/MinerU 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路…

使用 Python 快速完成管理系统开发:详细教程

如何使用 Python 快速完成管理系统开发&#xff1a;详细教程 Python 是一门功能强大且易于学习的编程语言&#xff0c;广泛应用于各种开发任务&#xff0c;包括管理系统开发。本文将详细介绍如何使用 Python 快速完成一个简单的管理系统开发&#xff0c;涵盖环境搭建、数据库设…

《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part1

资料来自李宏毅老师《生成式 AI》课程&#xff0c;如有侵权请通知下线 Introduction to Generative AI 2024 Spring 该文档主要介绍了国立台湾大学&#xff08;NTU&#xff09;2024 年春季 “生成式人工智能&#xff08;GenAI&#xff09;” 课程的作业 5&#xff08;GenAI HW…

LSA详情与特殊区域

LSA是构成LSDB的重要原材料&#xff0c;在OSPF中发挥很大作用。 报文 通用头部 LS age&#xff1a;LSA寿命&#xff0c;0-3600s Options&#xff1a;可选项 LS type&#xff1a;LSA类型&#xff0c;三要素之一 Link State ID&#xff1a;LSAID 三要素之一 Advertising Ro…

C#构建一个简单的循环神经网络,模拟对话

循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一种用于处理序列数据的神经网络模型。与传统的前馈神经网络不同&#xff0c;RNN具有内部记忆能力&#xff0c;可以捕捉到序列中元素之间的依赖关系。这种特性使得RNN在自然语言处理、语音识别、时间序列预…

线性代数的发展简史

线性代数的发展简史 线性代数作为数学的一个重要分支&#xff0c;其发展历史悠久而丰富。从古代文明中的基础计算到现代复杂的理论体系&#xff0c;线性代数经历了多个阶段的演变。 古代的起源 线性代数的雏形可以追溯到古埃及、古希腊、古印度和古代中国时期。这些早期文明…

网安瞭望台第4期:nuclei最新poc分享

国内外要闻 多款 D-Link 停产路由器漏洞&#xff1a;攻击者可远程执行代码 近日&#xff0c;知名网络硬件制造商 D-Link 发布重要安全公告。由于存在严重的远程代码执行&#xff08;RCE&#xff09;漏洞&#xff0c;其敦促用户淘汰并更换多款已停产的 VPN 路由器型号。 此次…

面试经典 150 题:205,55

205. 同构字符串 【解题思路】 来自大佬Krahets 【参考代码】 class Solution { public:bool isIsomorphic(string s, string t) {map<char, char> Smap, Tmap;for(int i0; i<s.size(); i){char a s[i], b t[i];//map容器存在该字符&#xff0c;且不等于之前映射…

IEC61850读服务器目录命令——GetServerDirectory介绍

IEC61850标准中的GetServerDirectory命令是变电站自动化系统中非常重要的一个功能&#xff0c;它主要用于读取服务器的目录信息&#xff0c;特别是服务器的逻辑设备节点&#xff08;LDevice&#xff09;信息。以下是对GetServerDirectory命令的详细介绍。 目录 一、命令功能 …

【PHP】 环境以及插件的配置,自学笔记(一)

文章目录 环境的准备安装 XAMPPWindowMacOS 配置开发环境Vscode 关于 PHP 的插件推荐Vscode 配置 php 环境Apache 启动Hello php配置热更新 参考 环境的准备 下载 XAMPP , 可以从 官网下载 https://www.apachefriends.org/download.html 安装 XAMPP XAMPP 是一个跨平台的集成开…

Jenkins-Git Parameter 插件实现指定版本的发布和回滚

在上一篇文章的基础设置上进行 1. 机器准备 开发10.0.0.204gitlab10.0.0.201jenkins10.0.0.200web10.0.0.202 2. 开发主机 在开发机器上修改不同版本的前端页面&#xff0c;并打上标签 第一次修改 [rootdev wheel]#vim index.html [rootdev wheel]#git commit -am "1…

神经网络10-Temporal Fusion Transformer (TFT)

Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型&#xff0c;它结合了Transformer架构和其他技术&#xff0c;旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出&#xff0c;旨在解决传统模型在时序预测中的一…

vue11.22

数据代理Object.defineproperty ler person { name:张三, sex:男, age:18 } console.log(Object.keys(person)) Object.keys是把对象的属性变成数组 let person { name: 张三, sex: 男, // age: 18 } Object.defineProperty(person, age, { value: 18 }) console.log(Obj…

1、HCIP之RSTP协议与STP相关安全配置

目录 RSTP—快速生成树协议 STP STP的缺点&#xff1a; STP的选举&#xff08;Listening状态中&#xff09;&#xff1a; RSTP P/A&#xff08;提议/同意&#xff09;机制 同步机制&#xff1a; 边缘端口的配置&#xff1a; RSTP的端口角色划分&#xff1a; ensp模拟…

【python系列】Python数据类型转换详解

在编程中&#xff0c;数据类型的正确使用和转换是开发中常见且重要的操作之一。Python 提供了隐式和显式两种数据类型转换方式。本文将详细介绍数据类型的基本概念、隐式和显式转换的区别与操作&#xff0c;并提供练习题帮助理解。 1. 数据类型概念及数据类型之间的区别 Pytho…

新160个crackme - 102-haggar-keyme1

运行分析 用win7或win xp系统可以运行输入Serial&#xff0c;点击Check无反应 PE分析 ASM程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 ida找到关键字符串 在sub_401E6B处按x&#xff0c;返回上一步函数 来到关键函数&#xff0c;静态分析逻辑如下&#xff1a;…

LCR-003比特位计数

一.题目&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 二.我的原始解法-一次性通过的python内置bin函数解法&#xff1a; 思路和题目描述一致&#xff0c;就是把0-n的每个数字转为二进制&#xff0c;计算这个二进制中1的个数添加到返回数组中&#xff0c;掌握基础函…

动态求连续区间和(线段树 树状数组)

向上更新&#xff0c;建树&#xff0c;求区间和&#xff0c;修改节点值 向上更新&#xff1a; 返回左右节点值的和 建树&#xff1a; 如果是叶子节点&#xff0c;赋值结构体的左区间&#xff0c;右区间&#xff0c;值 如果不是叶子节点&#xff0c;那么先求中点&#xff0c…

聊聊Flink:这次把Flink的window分类(滚动、滑动、会话、全局)、窗口函数讲透

一、窗口 窗口&#xff08;Window&#xff09;是处理无界流的关键所在。窗口将流分成有限大小的“桶”&#xff0c;我们可以在其上应用算子计算。Flink可以使用window()和windowAll()定义一个窗口&#xff0c;二者都需要传入一个窗口分配器WindowAssigner&#xff0c;WindowAs…

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…