惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
人人都是产品经理
人人都是产品经理
罗磊的独立博客
博客园 - 聂微东
雷峰网
雷峰网
量子位
美团技术团队
V
V2EX
The GitHub Blog
The GitHub Blog
大猫的无限游戏
大猫的无限游戏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
The Cloudflare Blog
爱范儿
爱范儿
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
Jina AI
Jina AI

祈雨的笔记

安全多方计算MPC spark原理解析 kueue执行源码分析 spark on k8s执行源码分析 spark-operator源码解析 系统压测遇到的缓存击穿问题 我的世界PC与安卓联机 蚂蚁金服流量投放平台的AIG改造 G1大对象致Old区占用率高 日志打印导致接口响应率下跌分析 Groovy加载类导致OOM分析 ERROR日志打印导致CPU满载 记OceanBase死锁超时 应用发版期间服务响应超时 Ark Serverless初探 系统优化复盘一二三 The user specified as a definer does not exist Kong网关初探 API网关选型调研 CPU火焰图常用工具 配置中心选型调研 root操作Nginx导致用户组错误 基于Proxifier使用代理 FastJSON字段智能匹配踩坑 Nacos初探 记一次Nginx服务器CPU满荷载故障 基于券系统分库分表的思考 limit不参与SQL成本计算致索引失效 Linux常用性能监控命令 golang低版本http2偶现400
mysql延时关联
祈雨的笔记 · 2020-04-03 · via 祈雨的笔记

描述

mysql有种sql优化方式,叫延时关联,即通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据,尤其在大分页查询的场景下,可以提高查询效率。例如下面两行SQL查询语句,在使用覆盖索引的大分页查询场景下,第二条的执行速度要远远快于第一条SQL。

1
2
3
select * from table where xxx limit a,b;

select * from table where id in (select id from table where xxx limit a,b);

在覆盖索引的场景下,第一条的执行逻辑是

  1. 通过索引找到(a+b)条符合查询条件的记录id
  2. 再通过(a+b)个id回表查询这(a+b)条记录
  3. 最后按分页条件给用户返回b条记录

而第二条SQL的执行逻辑则是

  1. 通过索引找到(a+b)条符合查询条件的记录id
  2. 按分页条件取b个记录id,然后回表查询这b条记录
  3. 最后给用户返回b条记录

不难看出,第二条SQL在覆盖索引的场景下,减少了大量的回表执行次数,从而提高了执行效率。而在非索引覆盖的场景下,延时关联失效,两种SQL的执行速度没有多少区别。

测试

创建一个测试表,并插入近200万条测试数据。

1
2
3
4
5
6
7
8
9
CREATE TABLE `salary_static` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`school_id` int(11) NOT NULL COMMENT '学校id',
`student_id` int(11) NOT NULL COMMENT '毕业生id',
`salary` int(11) NOT NULL DEFAULT '0' COMMENT '毕业薪水',
`year` int(11) NOT NULL COMMENT '毕业年份',
PRIMARY KEY (`id`),
KEY `year_key` (`year`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='毕业生薪水数据统计';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
delimiter  //
CREATE PROCEDURE init_salary_static()
BEGIN
DECLARE year INT;
DECLARE schid INT;
DECLARE stuid INT;
SET year = 2000;
WHILE year < 2020 DO
START TRANSACTION;
SET schid = 1;
WHILE schid < 100 DO
SET stuid = 1;
WHILE stuid < 1000 DO
insert into salary_static(school_id,student_id,salary,year) values (schid,stuid,floor(rand()*10000),year);
SET stuid = stuid + 1;
END WHILE;
SET schid = schid + 1;
END WHILE;
SET year = year + 1;
COMMIT;
END WHILE;
END //
delimiter ;

call init_salary_static();

覆盖索引的场景

1
2
3
4
5
select * from salary_static where year < 2010 limit 500000,10;

select s.* from salary_static s join
(select id from salary_static where year < 2010 limit 500000,10)
as tmp on (tmp.id = s.id);

image

由图可见,优化前sql查询平均需要大约0.8秒的时间,而通过延时关联优化后,则仅需要大约0.1秒的时间。即在覆盖索引的场景下,延时关联对于大分页查询可以有效提高查询效率。

回表的场景

1
2
3
4
5
select * from salary_static where year < 2010 and salary < 8000 limit 500000,10;

select s.* from salary_static s join
(select id from salary_static where year < 2010 and salary < 8000 limit 500000,10)
as tmp on (tmp.id = s.id);

image

由图可见,优化前sql查询平均需要大约1.2秒的时间,而通过延时关联优化后,依然需要大约1.2秒的时间。即在非覆盖索引的场景下,延时关联不能提高查询效率。