1 准备表结构

CREATE TABLE `student`  (
`id` int NOT NULL AUTO_INCREMENT,
`user_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`score` decimal(10, 2) NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

2 需求

按照成绩降序排列,并查询字段 user_no,user_name,score,做一个带排序的分页查询

3 自动执行数据

delimiter $$
CREATE PROCEDURE BatchInsert ( IN initId INT, IN loop_counts INT)BEGIN
DECLARE Var INT;
DECLARE ID INT; SET Var = 0;
SET ID = initId;
SET autocommit = 0; WHILE Var < loop_counts DO
INSERT INTO `test`.`student` ( `user_no`, `user_name`, `score`, `create_time`, `update_time` )
VALUES
(
CONCAT( '学号', ID ),
CONCAT( '姓名', ID ),
FLOOR( 1 + RAND()* 100 ),
DATE_ADD( '2023-3-30 16:08:00', INTERVAL ROUND( RAND()* 1000+1 ) DAY ),
DATE_ADD( '2023-3-30 16:08:00', INTERVAL ROUND( RAND()* 1000+1 ) DAY )
);
SET ID = ID + 1;
SET Var = Var + 1; END WHILE;
COMMIT; END $$;
delimiter;
CALL BatchInsert(1,2000000)

4 需要分页的sql

SELECT user_no,user_name,score FROM student ORDER BY score DESC LIMIT 5,20 #浅分页
SELECT user_no,user_name,score FROM student ORDER BY score DESC LIMIT 80000,20 #深分页

5 分页执行计划

通过执行计划 expladin 看下执行效率:

  • 浅分页:

  • 深分页:

可以看出 type=all 都是走的全表扫描,并且都使用了额外的文件排序,现在记录一下执行时间:

浅分页:0.887s,深分页:1.427s

5.1 对排序字段添加索引

对 score 添加索引:alter table student add index idx_score(score)

浅分页:

耗时:0.021s

深分页:

耗时:1.475s

可以看出,虽然对排序字段加了索引,但是由于深分页偏移量太大,还是选择了走全表扫描 type=all。并额外使用了文件排序。

可以分析出,排序需要成本,回表也需要成本,浅分页由于偏移量小,回表成本低,所以执行效率有很大的提升,深分页偏移量大,回表成本太高了,所以需要降低深分页回表的成本。

5.2 建立联合索引

建立联合索引,就是为了消除回表带来的效率损耗。

alter table student add index idx_no_name_score(score,user_no,user_name)

浅分页:

耗时:0.024s

深分页:

耗时:0.047s

可以看到,使用联合索引已经可以解决了回表的问题,两者的执行效率也高了很多,但是这种做法有一个缺点,如果我们要查询出来的数据多了一个字段,就得重建联合索引,这样扩展性太差肯定不能接受的。所以还有一种办法,手动回表。

5.3 手动回表

手动回表的前提是对order by 字段添加了索引

浅分页:

SELECT
user_no,
user_name,
score
FROM
student s1
JOIN ( SELECT id FROM student ORDER BY score DESC LIMIT 5, 20 ) s2 ON s1.id = s2.id

执行计划:

id 大的先执行

耗时:0.021s

深分页:

SELECT
user_no,
user_name,
score
FROM
student s1
JOIN ( SELECT id FROM student ORDER BY score DESC LIMIT 80000, 20 ) s2 ON s1.id = s2.id

执行计划:

耗时:0.042s

6 总结

优化方式 浅分页索引Type 深分页索引Type 浅分页耗时 深分页耗时
All All 0.887s 1.427s
order by 字段加索引 index All 0.021s 1.475s
联合索引 index index 0.024s 0.047s
手动回表(order by字段加索引) index index 0.021s 0.042s

实战SQL优化(以MySQL深分页为例)的更多相关文章

  1. atitit。mssql sql server 转换mysql 及 分页sql ast的搭建

    atitit.mssql sql server 转换mysql  及 分页sql ast的搭建 1. 主要的的转换::函数的转换,分页的转换 1 2. 思路::mssql sql >>as ...

  2. mysql的慢查询实战+sql优化

    背景:使用A电脑安装mysql,B电脑通过xshell方式连接,数据内容我都已经创建好,现在我已正常的进入到mysql中 步骤1:设置慢查询日志的超时时间,先查看日志存放路径查询慢日志的地址,因为有慢 ...

  3. 查询效率提升10倍!3种优化方案,帮你解决MySQL深分页问题

    开发经常遇到分页查询的需求,但是当翻页过多的时候,就会产生深分页,导致查询效率急剧下降. 有没有什么办法,能解决深分页的问题呢? 本文总结了三种优化方案,查询效率直接提升10倍,一起学习一下. 1. ...

  4. 正确使用索引(sql优化),limit分页优化,执行计划,慢日志查询

    查看表相关命令 - 查看表结构   desc 表名- 查看生成表的SQL   show create table 表名- 查看索引   show index from  表名 使用索引和不使用索引 由 ...

  5. 【SQL优化】MySQL官网中可优化的层次结构

    正如上一篇中我翻译的那篇文章,关于MySQL数据库优化的宏观介绍,了解到了从大体上来讲,优化MySQL可以从3个角度来讲.那么这一篇文章,则从一个个优化点出发,统计出究竟有多少个地方我们可以来优化My ...

  6. SQL优化-大数据量分页优化

    百万数据量SQL,在进行分页查询时会出现性能问题,例如我们使用PageHelper时,由于分页查询时,PageHelper会拦截查询的语句会进行两个步骤 1.添加 select count(*)fro ...

  7. MySQL 千万数据库深分页查询优化,拒绝线上故障!

    文章首发在公众号(龙台的技术笔记),之后同步到博客园和个人网站:xiaomage.info 优化项目代码过程中发现一个千万级数据深分页问题,缘由是这样的 库里有一张耗材 MCS_PROD 表,通过同步 ...

  8. SQL优化---慢SQL优化

    于2023.3.17日重写,之前写的还是太八股文太烂了一点逻辑都没有,这次重新写了之后,感觉数据库优化还是很有必要的,之前觉得不必要是我年轻了. 一.如何定位慢SQL语句 1.通过慢查询日志查询已经执 ...

  9. 工作中遇到的99%SQL优化,这里都能给你解决方案

    前几篇文章介绍了mysql的底层数据结构和mysql优化的神器explain.后台有些朋友说小强只介绍概念,平时使用还是一脸懵,强烈要求小强来一篇实战sql优化,经过周末两天的整理和总结,sql优化实 ...

  10. mysql实战优化之一:sql优化

    1.选取最适用的字段属性 MySQL 可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得 ...

随机推荐

  1. NL2SQL进阶系列(1):DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解

    NL2SQL进阶系列(1):DB-GPT-Hub.SQLcoder.Text2SQL开源应用实践详解 NL2SQL基础系列(1):业界顶尖排行榜.权威测评数据集及LLM大模型(Spider vs BI ...

  2. Python-List内部实现

    Python有很大实现的版本,像拿C语言实现的Cpython,以及在其基础上改进其解释执行变为即时编译(jit)的Pypy,还有一些其他的比如Jpython等.具体来说 其中使用c语言开发的叫做pyt ...

  3. 顺通鞋业MES生产工单管理系统软件

    顺通鞋业MES管理系统的"生产执行"是办公室和车间信息交互的枢纽,是一款针对大型鞋业生产企业开发的可配置化智能制造管理系统.工人可以通过车间终端(如安装在机器旁的固定工业触摸屏或移 ...

  4. 力扣378(java&python)-有序矩阵中第 K 小的元素(中等)

    题目: 给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素.请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素. 你必须找到一个 ...

  5. 力扣560(java&python)-和为k的子数组(中等)

    题目: 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 . 示例 1: 输入:nums = [1,1,1], k = 2输出:2示例 2: 输入:n ...

  6. InnoDB之UNDO LOG介绍

    简介: undo log是InnoDB事务特性的重要组成部分.当对记录做增删改操作就会产生undo记录,undo记录会记录到单独的表空间中. 本文将从代码层面对undo log进行一个简单的介绍:主要 ...

  7. MySQL 深潜 - MDL 锁的实现与获取机制

    简介:本文将介绍在 MDL 系统中常用的数据结构及含义,然后从实现角度讨论 MDL 的获取机制与死锁检测,最后分享在实践中如何监控 MDL 状态. ​ 作者 | 泊歌 来源 | 阿里技术公众号 一 背 ...

  8. WPF 通过 RawInput 获取触摸消息

    触摸在 Windows 下属于比较特殊的输入,不同于键盘和鼠标,键盘和鼠标可以通过全局 Hook 的方式获取到鼠标和键盘的输入消息.而触摸则没有直接的 Hook 的方法.如果期望自己的应用,可以在没有 ...

  9. aliyun全站DCDN刷新--Django

    1.编写原因: 由于登录到阿里云DCDN,需要登录加打开各种页面,导致推送一次感觉非常麻烦,所以编写(网上以有很多可以借鉴) 2.基础环境 # 所需模块 pip install aliyun-pyth ...

  10. keil 中未编译的代码灰色显示

    一.转载文章 转载:KEIL,#ifdef宏定义下失效代码差异性显示 注意keil的版本,太低的版本不具备灰色显示,据我所知在KEIL uVersion V5.31版本以上均可以. 二.使能灰色显示 ...