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. Hi3861编译烧录更快捷

     原文链接:https://mp.weixin.qq.com/s/TApbA6VUYUVWrGGaDyodbA,点击链接查看更多技术内容: HUAWEI DevEco Device Tool是华为面向 ...

  2. 堡垒机安装pytorch,mmcv,mmclassification,并训练自己的数据集

    堡垒机创建conda环境,并激活进入环境 conda create -n mmclassification python=3.7 conda activate mmclassification 堡垒机 ...

  3. 如何快速实现Prometheus监控Kubernetes集群

    Prometheus K8S集群中常见的监控工具有哪些: Kubernetes Dashboard Kube-monkey K8s-testsuite Kubespray Minikube Prome ...

  4. APISIX 简单的自定义插件开发步骤

    本文基于 APISIX 3.2 版本进行插件开发并运行通过. APISIX 目前开发插件比较简单,只需要编写 Lua 源代码并放到默认的插件目录下,然后通过配置文件开启插件即可,我们如果使用 Dock ...

  5. Java面试题:请谈谈对ThreadLocal的理解?

    ThreadLocal是一种特殊的变量存储机制,它提供了一种方式,可以在每个线程中保存数据,而不会受到其他线程的影响.这种机制在多线程编程中非常有用,因为它允许每个线程拥有自己的数据副本,从而避免了数 ...

  6. leetcode插件问题

    1.使用一段时间后,提交答案一直返回undefind 原因为插件缓存token有效期已过,需要重新登录 2. 重新登录

  7. 蚂蚁一面:GC垃圾回收时,内存分配和回收策略有哪些?

    文章首发于公众号:腐烂的橘子 蚂蚁面试主要为电话面试,期间也会要求使用编辑器手写算法题.作为一线互联网大厂,Java 基础知识是必备的,其中垃圾回收也是面试过程中的重中之重. Java 内存的自动管理 ...

  8. opensips开启python支持

    操作系统 :CentOS 7.6_x64   opensips版本: 2.4.9   python版本:2.7.5 python作为脚本语言,使用起来很方便,查了下opensips的文档,支持使用py ...

  9. [FE] 推荐两个能全球访问的 CDN 前端资源仓库

    https://unpkg.com/ https://cdnjs.com/ 部分资源库的版本不全. 访问速度请自行评估. Link:https://www.cnblogs.com/farwish/p/ ...

  10. dotnet 6 数组拷贝性能对比

    本文来对比多个不同的方法进行数组拷贝,和测试其性能 测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信.在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试.详细请 ...