MySQL:SQL调优的简单实践

news2024/9/23 23:31:15

记一次简单的SQL优化实践。

一、初始化数据

1.1 初始化数据-课程表

#课程表
create table Course(
	c_id int primary key,
	name varchar(10)
);

 #存储过程:增加课程表100条数据
 DROP PROCEDURE IF EXISTS insert_Course;

 DELIMITER $
 CREATE PROCEDURE insert_Course()
 BEGIN
     DECLARE i INT DEFAULT 1;
         WHILE i<=100 DO
         INSERT INTO Course(`c_id`,`name`) VALUES(i, CONCAT('语文',i+''));
         SET i = i+1;
    END WHILE;
END $

CALL insert_Course();

1.2 初始化数据-学生表

#学生表
create table Student(
	s_id int primary key,
	name varchar(10)
);

#存储过程:学生表增加70000条数据
 DROP PROCEDURE IF EXISTS insert_Student;
 
 DELIMITER $
 CREATE PROCEDURE insert_Student()
 BEGIN
     DECLARE i INT DEFAULT 1;
         WHILE i<=70000 DO
         INSERT INTO Student(`s_id`,`name`) VALUES(i, CONCAT('张三',i+''));
         SET i = i+1;
    END WHILE;
END $

CALL insert_Student();

1.3 初始化数据-成绩表

#成绩表
CREATE table Result(
	r_id int primary key,
	s_id int,
	c_id int,
	score int
);

#存储过程:成绩表增加70W条数据
 DROP PROCEDURE IF EXISTS insert_Result;
 
 DELIMITER $
 CREATE PROCEDURE insert_Result()
 BEGIN
     DECLARE i INT DEFAULT 1;
         DECLARE sNum INT DEFAULT 1;
         DECLARE cNum INT DEFAULT 1;
         WHILE i<=700000 DO
                if (sNum%70000 = 0) THEN
                    set sNum = 1;
                elseif (cNum%100 = 0) THEN 
                    set cNum = 1;
                end if;
        INSERT INTO Result(`r_id`,`s_id`,`c_id`,`score`) VALUES(i,sNum ,cNum , (RAND()*99)+1);
        SET i = i+1;
                SET sNum = sNum+1;
                SET cNum = cNum+1;
    END WHILE;
END $

CALL insert_Result();

二、SQL实践

业务需求:查找 语文1 成绩为 100 分的考生

2.1 基础子查询

#查询语文1考100分的考生
select s.* from Student s where s.s_id in (
	select s_id from Result r where r.c_id = 1 and r.score = 100
)

执行时间:0.937s
查询结果:32 位满足条件的学生

查看执行计划:

EXPLAIN select s.* from Student s where s.s_id in (
	select s_id from Result r where r.c_id = 1 and r.score = 100
)

查询结果中 type 列:all 是全表扫描,index 是通过索引扫描。
在这里插入图片描述

2.2 优化-创建索引

根据执行计划:发现没有用到索引,type 全是 ALL ,那么首先想到的就是建立一个索引,建立索引的字段当然是在 where 条件的字段了。

先给 Result 表的 c_id 和 score 建立个索引:

CREATE index result_c_id_index on Result(c_id);
CREATE index result_score_index on Result(score);

再次执行上述查询语句,时间为:0.027s。

快了 34.7 倍(四舍五入),大大缩短了查询的时间,看来索引能极大程度的提高查询效率,在合适的列上面建立索引很有必要。

相同的 SQL 语句多次执行,你会发现第一次是最久的,后面执行所需的时间会比第一次执行短些许。原因是:相同语句第二次查询会直接从缓存中读取。

2.3 优化-SQL优化-连接查询(1)

0.027s 很短了,但是还能再进行优化吗,再次查看执行计划:

EXPLAIN select s.* from Student s where s.s_id in (
	select s_id from Result r where r.c_id = 1 and r.score = 100
)

show warnings;

(1)执行计划结果:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/997b21c5063c448b92578f2929ed7808.png
(2)优化后的SQL:

 SELECT
     `example`.`s`.`s_id` AS `s_id`,
     `example`.`s`.`name` AS `name` 
 FROM
     `example`.`Student` `s` semi
     JOIN ( `example`.`Result` `r` ) 
 WHERE
     (
     	( `example`.`s`.`s_id` = `<subquery2>`.`s_id` ) 
    	AND ( `example`.`r`.`score` = 100 ) 
    	AND ( `example`.`r`.`c_id` = 1 ) 
    )

有 type = all。按照之前的想法,该 SQL 执行的顺序是执行子查询获取s_id结果。

12871,40987,46729,61381,3955,10687,14047,26917,28897,31174,38896,56518,10774,25030,9778,12544,24721,27295,60361,
38479,46990,66988,6790,35995,46192,47578,58171,63220,6685,67372,46279,64693

然后在执行如下SQL:

select s.* from Student s where s.s_id in (
	12871,40987,46729,61381,3955,10687,14047,26917,28897,31174,38896,56518,10774,25030,9778,12544,24721,27295,60361,38479,46990,66988,6790,35995,46192,47578,58171,63220,6685,67372,46279,64693
)

单独执行上述SQL耗时0.222s。发现比一起执行快多了,查看优化后的 SQL 语句,发现MySQL 竟然不是先执行里层的查询,而是将 SQL 优化成了 exists 字句,执行计划中的 select_type 为 MATERIALIZED(物化子查询)。MySQL 先执行外层查询,在执行里层的查询,这样就要循环学生数量*满足条件的学生 ID 次,也就是 7W * 32 次。

我们将SQL修改为连接查询,如下:

select s.* from Student s INNER JOIN Result r on r.s_id = s.s_id where r.c_id = 1 and r.score = 100;

这里为了重新分析连接查询的情况,先暂时删除索引 result_c_id_index ,result_score_index ,并基于连接查询创建索引。

DROP index result_c_id_index on Result;
DROP index result_score_index on Result;

CREATE index result_s_id_index on Result(s_id);

执行耗时 1.2s ,再来看看执行计划( EXPLAIN + 查询 SQL 即可查看该 SQL 的执行计划):
(1)创建基于连接查询的索引前:
在这里插入图片描述
(2)创建基于连接查询的索引后:
在这里插入图片描述
发现是先做的连接查询,再进行的 where 条件过滤。但是我们这里的情况,如果先 join ,将会有 70W 条数据发送 join ,所以先执行Result。

2.4 优化-SQL优化-连接查询(2)

优化的SQL如下:

SELECT s.* FROM (
	SELECT * FROM Result r WHERE r.c_id = 1 AND r.score = 100 
) t INNER JOIN Student s ON t.s_id = s.s_id

比之前 sql 的时间都要短,查看执行计划:
在这里插入图片描述
再给 Result 表的 c_id 和 score 建立个索引:

CREATE index result_c_id_index on Result(c_id);
CREATE index result_score_index on Result(score);

在这里插入图片描述
这里用到了 intersect 并集操作,即两个索引同时检索的结果再求并集,再看字段 score 和 c_id 的区分度,但从一个字段看,区分度都不是很大,从 Result 表检索,c_id = 81 检索的结果是 81 ,score = 84 的结果是 84 。而 c_id = 81 and score = 84 的结果是 19881,即这两个字段联合起来的区分度还是比较高的,因此建立联合索引查询效率将会更高,从另外一个角度看,该表的数据是 300W ,以后会更多,就索引存储而言,都是不小的数目,随着数据量的增加,索引就不能全部加载到内存,而是要从磁盘读取,这样索引的个数越多,读磁盘的开销就越大,因此根据具体业务情况建立多列的联合索引是必要的。

三、小结

1、MySQL 嵌套子查询效率确实比较低,可以将其优化成连接查询。
2、连接表时,可以先用 where 条件对表进行过滤,然后做表连接( MySQL 默认会对连表语句做优化)。
3、建立合适的索引,必要时建立多列联合索引
4、学会分析 sql 执行计划,mysql 会对 sql 进行优化,所有分析计划很重要。

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

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

相关文章

[线程]***多线程带来的风险-线程安全问题

文章目录 一. 什么是线程安全二. 线程不安全一个经典的例子三. 对上述例子的理解四. 出现线程不安全的原因1. 线程在操作系统中是随机调度, 抢占式执行的2. 当前代码中, 多个线程同时修改同一变量3. 线程针对变量的修改操作, 不是"原子"的4. 内存可见性问题, 引起线程…

使用gradle 移除敏感权限

前言 最近要上架Google Play 但是因为有个敏感权限很容易被拒。 想着把权限依赖的库去掉就行了&#xff0c;但是遇到一个恶心的问题。就是这个权限在Android Studio的Merged Manifest 视图中没有&#xff0c;但是在生成的apk中却包含。这样的就不能通过Android Studio来定位权…

一文搞懂 js 原型和原型链

文章目录 一、前言二、原型2.1 概念2.2 获取原型的方法2.2.1 __proto__获取方式2.2.2 通过构造函数prototype 属性获取2.2.2 ES6 class 通过Object.getPrototypeOf()获取类原型 2.3 通过原型实现继承2.4 原型的作用 三、 原型链四、ES6实现继承五、综述 一、前言 原型和原型链…

计算机网络面试真题总结(七)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 什么是对称加密、非对称加密&#xff1f; 对称加密是一种常用的加…

C语言 之 自定义类型:结构体、结构体内存对齐、修改默认对齐参数 详细说明 可以来看看哟

结构体类型的声明 结构体的声明 struct tag {member-list; //结构体中的成员&#xff0c;可以有多个 }variable-list; //这里是直接创建结构体的变量&#xff0c;但是不一定要在这里声明变量 //不能把后面这个 ; 省略了例如结构体用于描述一个学生&#xff1a; struct Stu…

MySQL内部临时表(Using temporary)案例详解及优化解决方法

目录 前言 一.场景案例 二、什么是内部临时表&#xff1f; 三、哪些场景会使用内部临时表&#xff1f; 四、内部临时表如何存储&#xff1f; 1&#xff09;使用内存 2&#xff09;先使用内存&#xff0c;再转化成磁盘文件 3&#xff09;直接使用磁盘文件 五、如何优化…

Stable Diffusion绘画 | ControlNet应用-IP-Adapter:一致性角色就这么简单

IP-Adapter 更新了全新的模型—FaceID plus V2 版本&#xff0c;同时还支持 SDXL 模型。 FaceID plus V2 版本的优点&#xff1a; 解决任务一致性 一张图生成相似角色 其中&#xff0c;两个 Lora文件 放置在&#xff1a;SD安装目录\models\Lora 两个 bin文件 放置在&#x…

三、IIC 总线协议——1、IIC总线协议介绍

IIC总线协议介绍 1、IIC介绍&#xff1a; Inter Integrated Circuit&#xff0c;同步、串行、半双工通信总线。 2、IIC总线结构图 ① 由时钟线SCL和数据线SDA组成&#xff0c;并且都接上拉电阻&#xff0c;确保总线空闲状态为高电平。 ②总线支持多设备连接&#xff0c;允许…

SSM电动车智能充电桩管理系统 项目源码24481

摘 要 随着社会对环保和可持续发展的关注不断增加&#xff0c;电动车作为清洁能源交通工具受到了广泛关注和推广。然而&#xff0c;电动车充电设施的建设和管理面临着诸多挑战&#xff0c;如充电效率低下、管理繁琐等问题。为解决这些问题&#xff0c;本研究设计开发了一款电…

揭秘无线领夹麦克风五大行业隐秘:音质失真、隐私泄露需警惕!

​无线领夹麦克风是演讲、教学、直播等场合的得力助手&#xff0c;然而市场上品牌众多&#xff0c;产品质量参差不齐&#xff0c;安全隐患层出不穷。作为一名音频设备评测师&#xff0c;我近期入手了多款无线领夹麦克风进行测评&#xff0c;下面就来为大家揭秘无线领夹麦克风行…

Jupyter Notebook详细教程

1、Ipython介绍 介绍 科学计算标准工具集的组成部分 IPython是一个免费、开源的项目&#xff0c;支持Linux、Unix、Mac OS X和Windows平台&#xff0c;其官方网址&#xff1a;Jupyter and the future of IPython — IPython IPython中包括各种组件&#xff0c;其中的两个主要…

无盘设计及其在Allegro中的具体操作

无盘设计的好处有两点&#xff1a; 去掉焊环后&#xff0c;增加了孔与线或是其它孔的间距; 去掉焊环后&#xff0c;铜皮避让的面积更少了&#xff0c;增加了铺铜平面的完整性。 一、确定通孔/过孔焊盘支持去除焊环 只有在封装中勾选了Suppress unconnected internal pads; leg…

AI大模型,互联网的中年革命?人才抢夺白热化,平均工资水平惊呆了……

写在前面 在腾讯股东大会上&#xff0c;CEO马化腾深刻指出&#xff0c;人工智能&#xff08;AI&#xff09;并非仅仅是互联网领域十年一遇的机遇&#xff0c;而是一个具有深远影响的、堪比电力发明的工业革命级别的重大机遇。 本文将包括&#xff1a; 1- 行业概览 2- 大模型…

C++必修:bitset的用法与实现

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 位图的引入 首先我们来看一道面试题&#xff1a; 给40亿个不重复的无符号整数…

乌龙?揭露2024国自然被刷真相!

8月24日&#xff0c;国自然正式放榜&#xff0c;并且申请项目批准资助通知、不予资助通知以及专家评审意见也已发送到各位申请人手里。 中了的人兴奋庆祝&#xff0c;没中的人气愤懊恼&#xff0c;一遍又一遍的看着评审意见&#xff0c;甚至会质疑一些评审的意见有些 “不合理…

The Power of Scale for Parameter-Efficient Prompt Tuning

系列论文研读目录 文章目录 系列论文研读目录论文题目含义Abstract1 Introduction2 Prompt Tuning5.6.7.8.9.10. 论文链接 论文题目含义 刻度在参数高效快速调优中的作用 Abstract In this work, we explore “prompt tuning,” a simple yet effective mechanism for lear…

(四)Kafka离线安装 - Kafka下载及安装

Kafka官方下载地址&#xff1a;Apache Kafka 这时候下载安装版本。 我这里的安装目录在 /usr/local/ cd /usr/local/# 创建目录 mkdir kafka cd kafka mkdir kafka_log 把下载的压缩包&#xff0c;放入到/usr/local/kafka/目录下&#xff0c;解压。 # 解压 tar -zxvf kafka…

PDF招生简章如何转二维码?

​随着科技的不断发展&#xff0c;招生报名方式也在不断创新。如今&#xff0c;许多学校和企业都采用PDF招生简章来宣传招生。然而&#xff0c;传统的纸质招生简章存在携带不便、易损坏等问题。为了解决这些问题&#xff0c;将PDF招生简章转换为二维码成为了一种趋势。那你知道…

Laravel邮件发送功能的实现的方法和技巧?

Laravel邮件发信功能如何配置&#xff1f;怎么使用Laravel发信&#xff1f; 在现代Web开发中&#xff0c;邮件发送功能是不可或缺的一部分。Laravel框架以其优雅的语法和强大的功能&#xff0c;成为了许多开发者的首选。AokSend将深入探讨如何在Laravel中实现邮件发送功能&…

让甲方看得见服务器资源降本增效-软件开发不仅考虑开发成本也要重视长期的运维成本

这几天有几个开发者朋友问&#xff0c;用Go语言开发后端真能降低服务器成本吗&#xff1f;本文想分享是低成本一种解决方案&#xff0c;我们不讨论谁是世界上最好的开发语言&#xff0c;所以开发者朋友看到对比语言就不要去挣个高低。GoFly社区今天给大家分享我们这几年用下来真…