MySQL数据库调优之关联查询、排序查询、分页查询、子查询、Group by优化

news2025/1/20 18:32:19

关联查询优化

1.准备工作

CREATE TABLE IF NOT EXISTS `type`(
   id INT(10) UNSIGNED NOT NULL  AUTO_INCREMENT,
   card INT(10) UNSIGNED NOT NULL,
   PRIMARY KEY(id)

);

CREATE TABLE IF NOT EXISTS book(
bookid INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
card INT(10) UNSIGNED NOT NULL,
PRIMARY KEY(bookid)
)

INSERT INTO TYPE(card) VALUES (FLOOR (1+(RAND()*20)));


INSERT INTO book(card) VALUES (FLOOR (1+(RAND()*20)));

情况1:左外连接

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card=book.card;

在这里插入图片描述
添加索引后

CREATE INDEX Y ON book(card);

在这里插入图片描述
内连接

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON type.card=book.card;

在这里插入图片描述
对于内连接来说,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的

删除被驱动表book的index后
在这里插入图片描述
对于内连接来说,如果表的连接条件中只能有一个字段有索引,则有索引的字段所在的表会被作为被驱动表出现
在这里插入图片描述
对于内连接来说,在两个表的连接条件都存在索引的情况下,会选择小表作为驱动表。“小表驱动大表”

join语句的原理

驱动表和被驱动表
驱动表是主表,被驱动表是从表,非驱动表。
对于内连接来说:

SELECT * FORM A JOIN B ON...

A一定是驱动表么? 不一定,优化器会根据你查询语句做优化,决定先查那张表,先查询的那张表就是驱动表,反之就是被驱动表。通过explain关键字可以查看。

对于外连接来说:

SELECT * FROM A LEFT JOIN B ON ...
SELECT * FROM B RIGHT JOIN A ON ....

通常会认为A为驱动表,B为被驱动表,但也未必

Simple Nested-Loop Join(简单嵌套循环连接)

在这里插入图片描述
在这里插入图片描述
**

Index Nested-Loop join (索引嵌套循环连接)

**
index nested-loop join其优化的思路主要是为了减少内层表数据的匹配次数,所以要求·被驱动表上必须有索引才行。通过外层表匹配条件直接与内层表索引进行匹配,避免和内层表的每条记录去进行比较,这样极大的减少了对内层表的匹配次数。

在这里插入图片描述
在这里插入图片描述

Block Nested Loop Join(块嵌套循环连接)

在这里插入图片描述
JOIN BUFFER缓冲区缓存的不只是关联表的列,select后面的列也会缓存起来
在这里插入图片描述
在这里插入图片描述
参数设置
block_nested_loop=on

SHOW VARIABLES LIKE  '%optimizer_switch%'
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on

join_buffer_size 默认256K

SHOW VARIABLES LIKE  '%join_buffer_size%'

在这里插入图片描述
JOIN小结
在这里插入图片描述

Hash Join
从Mysql的8.0.20版本开始将废弃BNLJ,因为从Mysql8.0.18版本开始就加入了hash join,默认都是用hash join

在这里插入图片描述
JOIN连接 小结
保证被驱动表的JOIN字段已经创建了索引
需要JOIN的字段,数据类型保持绝对的一致
left join时,选择小的作为驱动表,大表作为被驱动表。减少外层循环的次数
inner join 时,mysql会自动将小结果集的表选为驱动表 选择相信mysql优化策略。
能够直接多表关联的尽量直接关联,不用子查询(减少查询的趟数)
不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用JOIN来代替子查询。
衍生表建不了索引

子查询优化

Mysql从4.1版本开始支持子查询,使用子查询可以进行SELECT语句的嵌套查询,即一盒SELECT查询的结果作为另外一个SELECT 语句的条件。子查询可以一次性完成很多逻辑上需要多个步骤才能完成的SQL操作
子查询是Mysql的一项重要的功能,可以帮助我们通过一个SQL语句实现比较复杂的查询。但是,子查询的执行效率不高。原因
1.执行子查询时,Mysql需要为内层查询语句的查询结果建立一个临时表,然后外层查询语句从临时表中查询记录。查询完毕后,再撤销这些临时表。这样会消耗过多的CPU和IO资源,产生大量的慢查询。
2.子查询的结果集存储的临时表,不论是内存临时表还是磁盘临时表都不会存在索引,索引查询的性能会有一定的影响。
对于返回结果集比较大的子查询,其对查询性能的影响也越大。
在Mysql中,可以使用连接(JOIN)查询来代替子查询。连接查询不需要建立临时表其速度比子查询要快。如果查询中有使用索引的话,性能就会更好。

尽量不要使用NOT IN 或者NOT EXISTS,用LEFT JOIN xxxxx ON xx WHERE xx IS NULL 替代

排序优化

问题:在where条件字段上加索引,但是为什么在Order by字段上还要加索引呢?
回答
在mysql中,支持两种排序方式,分别是FileSortIndex排序
Index排序中,索引可以保证数据的有序性,不需要再进行排序,效率更高
FileSort排序则一般在内存中进行排序,占用CPU较多,如果待排结果较大,会产生临时文件I/0到磁盘进行排序的情况,效率更低。
优化建议:
1.SQL 中,可以在Where子句和Order子句中使用索引,目的时在WHERE子句中避免全表扫描,Order By子句避免使用FileSort排序。当然在某些情况下,全表扫描或者FileSort排序不一定比索引慢。但总的来说,我们还是要避免,以提高查询效率。
2.尽量使用Index完成Order by排序。如果Where和Order by后面是相同的列就使用单索引列;如果不同就使用联合索引。
3.无法使用Index时,需要对FileSort方式进行调优。
select的查询内容没有限制
在这里插入图片描述

select查询内容与索引保持一致(索引覆盖)
在这里插入图片描述
增加limit过滤条件,使用上了索引
在这里插入图片描述
order by时顺序错误,索引失效
在这里插入图片描述
在这里插入图片描述
上述案例违反了索引的最左匹配的原则
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上述三种情况,索引有在使用中

order by 时规则不一致,索引失效(顺序错,不索引;方向反,不索引)

EXPLAIN SELECT * FROM student ORDER BY age DESC,classid ASC LIMIT 10;

EXPLAIN SELECT * FROM student ORDER BY classid DESC,NAME ASC LIMIT 10;

EXPLAIN SELECT * FROM student ORDER BY age ASC,classid DESC LIMIT 10;

EXPLAIN SELECT * FROM student ORDER BY age DESC,classid DESC LIMIT 10;


只要最后一种倒着来的使用上了索引

无过滤,不索引


#无过滤,不索引

EXPLAIN SELECT * FROM student WHERE age=45 ORDER BY classid; #先使用where 过滤数据 ken_len=5

EXPLAIN SELECT * FROM student WHERE age=45 ORDER BY classid,NAME; #先使用where 过滤数据 ken_len=5

EXPLAIN SELECT * FROM student WHERE classid=45 ORDER BY age; #没用

EXPLAIN SELECT * FROM student WHERE classid=45 ORDER BY age LIMIT 10; #用了索引

小结
在这里插入图片描述
在这里插入图片描述
结论:
1.两个索引同时存在,mysql会自动选择最优方案。但是,随着数据量的变化,选择的索引也会随之变化
2.当【范围条件】和【group by或者order by】的字段出现二选一时,优先观察条件字段的过滤数量,如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段上,反之,亦然。

fileSort算法:双路排序和单路排序

排序的字段若如果不在索引列上,则filesort会有两种算法:双路排序和单路排序

在这里插入图片描述
在这里插入图片描述
Order by时select 是一个大忌,最好只query需要的字段
原因:
当query的字段大小总和小于
max_length_for_sort_data*,而且排序的字段不是TEXT|BLOB类型时,会用改进的算法–单路排序,否则用老算法–多路排序.
两种算法的数据都有可能超出sort_buffer_size的容量,超出之后,会创建tmp文件进行合并排序,导致多次I/0,但是用单路排序的风险更大一些,所以要提高sort_buffer_size的容量

Group 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 这些查询的语句,where条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

优化分页查询

一般分页查询时,通过创建覆盖索引能够比较好的提高性能。一个常见又比较头疼的问题就是limit 2000000,10 此时,需要mysql排序前20000010条记录,仅仅返回2000000-20000010的记录,其他记录丢弃,查询排序的代价非常的大。

EXPLAIN SELECT * FROM student  LIMIT 2000000,10;

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

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

在这里插入图片描述
优化思路二:
改方案适合于主键自增的表,可以把limit查询转换成某个位置的查询

EXPLAIN SELECT * FROM student  WHERE id> 2000000 LIMIT 10;

在这里插入图片描述

Exists和In的区别

问题:
不太理解哪种情况下应该使用EXISTS,哪种情况应该用IN,选择的标准是看能否使用表的索引么?
回答:
索引是一个前提,其实选择与否还是要看表的大小。可以将选择的标准理解为小表驱动大表。在这种方式下效率是高的。

在这里插入图片描述

Count(*)与Count(具体字段)效率

问题: 在mysql中统计数据表的行数,可以使用三种方式:SELECT COUNT(*)\SELECT COUNT(1)和SELECT COUNT(具体字段),使用三者之间的查询效率是怎么样的?
前提: 如果要统计的是某个字段的非空数据行数,则另当别论,毕竟比较执行效率的前提是结果是一样的。
在这里插入图片描述

关于SELECT (*)

在表查询中,建议明确字段,不要用作为查询的字段列表,推荐使用SELECT <字段列表> 查询。
原因:
mysql在解析的过程中,会通过查询数据字典
按序转化为所有列名,这样会大大的耗费资源和时间。无法使用覆盖索引

LIMIT 1 对优化的影响

针对的是会扫描全表的SQL语句,如果你可以确定结果集只有一条,那么加上limit 1 时**,当找到结果的时候就不会继续扫描了,这样会加快查询速度**。

如果数据表已经对字段建立了唯一索引,那么可以使用索引进行查询,不会全表扫描的话,就不需要加上limit 1了

多使用COMMIT

在这里插入图片描述

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

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

相关文章

智慧应急与物联网相结合:物联网技术如何提升智慧应急响应能力

目录 一、引言 二、智慧应急与物联网技术的结合 三、物联网技术提升智慧应急响应能力的途径 四、物联网技术在智慧应急中的应用案例 五、物联网技术在智慧应急中面临的挑战与解决方案 挑战一&#xff1a;技术标准与规范不统一 解决方案&#xff1a; 挑战二&#xff1a;…

【考研数学】基础阶段习题1800和660怎么选❓

我建议以1800题为主 1800题包含基础和强化两部分&#xff0c;基础部分题量很大&#xff0c;类型也很全面&#xff0c;并且难度一点也不高&#xff0c;适合基础不好的学生来做。 660题难度比较大&#xff0c;不适合基础阶段做。 660题虽然名字叫基础训练&#xff0c;但是不适…

英语连读技巧15

1. first one – 第一个 连读听起来就像是&#xff1a;【佛斯湾】 连读的音标为&#xff1a; 例句&#xff1a;I don’t want to be the first one there agin. 发音指导&#xff1a;在“first one”的连读中&#xff0c;"t"和"o"之间的连接几乎消失&a…

Java线程池实现原理详解

线程池是什么 线程池&#xff08;Thread Pool&#xff09;是一种基于池化思想管理线程的工具&#xff0c;经常出现在多线程服务器中&#xff0c;如MySQL。 线程过多会带来额外的开销&#xff0c;其中包括创建销毁线程的开销、调度线程的开销等等&#xff0c;同时也降低了计算…

03|Order by与Group by优化

索引顺序依次是 &#xff1a; name,age,position 案例1 EXPLAIN SELECT * FROM employees WHERE name LiLei AND position dev ORDER BY age;分析: 联合索引中只是用到了name字段做等值查询[通过key_len 74可以看出因为name字段的len74]&#xff0c;在这个基础上使用了age进…

sql-labs32关宽字节注入

一、环境 网上有自己找很快 二、如何通关 2.1解释 虚假预编译没有参数绑定的过程&#xff0c;真实预编译有参数绑定的过程 宽字节注入出现的本质就是因为数据库的编码与代码的编码不同&#xff0c;导致用户可以通过输入精心构造的数据通过编码转换吞掉转义字符。 在32关中…

华为HCIP Datacom H12-831 卷24

多选题 1、如图所示&#xff0c;某园区部署OSPF实现网络互通&#xff0c;其中Area1部署为NSSA区域。某工程师为了实现R1访问R4的环回口地址&#xff0c;在R4的OSPF进程中引入直连路由。以下关于该场景的描述,错误的有哪些项? A、在R4引入直连路由后&#xff0c;R1通过转换后的…

Java基于物联网技术的智慧工地云管理平台源码 依托丰富的设备接口标准库,快速接入工地现场各类型设备

目录 风险感知全面化 项目进度清晰化 环境监测实时化 人员管理高效化 工地数字化 数据网络化 管理智慧化 智慧工地平台整体架构 1个可扩展监管平台 2个应用端 3方数据融合 N个智能设备 智慧工地的远程监管&#xff0c;是工地负责人掌握施工现场情况的必要手段&…

第6.4章:StarRocks查询加速——Colocation Join

目录 一、StarRocks数据划分 1.1 分区 1.2 分桶 二、Colocation Join实现原理 2.1 Colocate Join概述 2.2 Colocate Join实现原理 三、应用案例 注&#xff1a;本篇文章阐述的是StarRocks-3.2版本的Colocation Join 官网文章地址&#xff1a; Colocate Join | StarRoc…

JAVA算法和数据结构

一、Arrays类 1.1 Arrays基本使用 我们先认识一下Arrays是干什么用的&#xff0c;Arrays是操作数组的工具类&#xff0c;它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。 下面我们用代码来演示一下&#xff1a;遍历、拷贝、排序等操作。需要用到的方法如下 public…

SpringMVC 学习(五)之域对象

目录 1 域对象介绍 2 向 request 域对象共享数据 2.1 通过 ServletAPI (HttpServletRequest) 向 request 域对象共享数据 2.2 通过 ModelAndView 向 request 域对象共享数据 2.3 通过 Model 向 request 域对象共享数据 2.4 通过 map 向 request 域对象共享数据 2.5 通过…

音视频数字化(数字与模拟-电影)

针对电视屏幕,电影被称为“大荧幕”,也是娱乐行业的顶尖产业。作为一项综合艺术,从被发明至今,近200年的发展史中,无人可以替代,并始终走在时代的前列。 电影回放的原理就是“视觉残留”,也就是快速移过眼前的画面,会在人的大脑中残留短暂的时间,随着画面不断地移过,…

智慧城市,未来已来:数字中国建设中的创新实践

随着数字技术的飞速发展&#xff0c;中国正迎来一个全新的智慧城市时代。在这个时代&#xff0c;城市的每一个角落都充满了科技的气息&#xff0c;人们的生活也因此变得更加便捷、高效和美好。今天&#xff0c;就让我们一起走进这个充满未来感的智慧城市&#xff0c;探索数字中…

onlyoffice api开发

编写代码 按照https://api.onlyoffice.com/editors/basic编写代码 <html> <head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scal…

长短连接对压测的影响有多大

【引言】 当我们进行压力测试时&#xff0c;长短连接是一个非常重要的参数。但是&#xff0c;你知道吗&#xff1f;长短连接对于压测结果有着非常大的影响&#xff01;如果你不理解这个参数&#xff0c;那么你的压测结果可能会出现严重的偏差。 在这篇文章中&#xff0c;我将…

使用 yarn 的时候,遇到 Error [ERR_REQUIRE_ESM]: require() of ES Module 怎么解决?

晚上回到家&#xff0c;我打开自己的项目&#xff0c;执行&#xff1a; cd HexoPress git pull --rebase yarn install yarn dev拉取在公司 push 的代码&#xff0c;然后更新依赖&#xff0c;最后开始今晚的开发时候&#xff0c;意外发生了&#xff0c;竟然报错了&#xff0c;…

吴恩达deeplearning.ai:Tensorflow训练一个神经网络

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai 在之前的博客中。我们陆续学习了各个方面的有关深度学习的内容&#xff0c;今天可以从头开始训练一个神经网络了。 Tensorflow训练神经网络模型 我们使用之前用过的例子&#xff1a; 这个神经…

软件开发的艺术与科学

随着科技的飞速发展&#xff0c;软件开发已成为当今社会不可或缺的一部分。从智能手机应用程序到企业级管理系统&#xff0c;软件开发已经渗透到我们生活的方方面面。本文将探讨软件开发的重要性和现状&#xff0c;以及开发过程中涉及的关键环节和常见问题。 一、软件开发的重…

leetcode:491.递增子序列

1.误区&#xff1a;不能直接对数组排序再求解子集&#xff0c;因为那样就改变了原有数组的顺序 2.树形结构&#xff1a;一个一个取数&#xff0c;然后保证是递增序列&#xff0c;且不能重复。&#xff08;数层上不可以重复取&#xff0c;树枝上可以重复取&#xff09;收集的结…

Android BitmapDrawable.bitmap与BitmapFactory.decodeResource获取不到原始图像素级真实宽高,Kotlin

Android BitmapDrawable.bitmap与BitmapFactory.decodeResource获取不到原始图像素级真实宽高&#xff0c;Kotlin 当一个图片放在ImageView里面后&#xff0c;用以下方式获取图的宽高&#xff1a; val bmp1 (this.drawable as BitmapDrawable).bitmapLog.d("fly", &…