在线精品99_中国九九盗摄偷拍偷看_91免费版在线观看_91.app_91高清视频在线_99热最新网站

mysql查询时offset过大影响性能的原因是什么

104次阅读
没有评论

共计 5282 个字符,预计需要花费 14 分钟才能阅读完成。

这篇文章主要介绍了 mysql 查询时 offset 过大影响性能的原因是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让丸趣 TV 小编带着大家一起了解一下。

准备测试数据表及数据

1. 创建表

CREATE TABLE `member` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(10) NOT NULL COMMENT  姓名 ,
 `gender` tinyint(3) unsigned NOT NULL COMMENT  性别 ,
 PRIMARY KEY (`id`),
 KEY `gender` (`gender`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. 插入 1000000 条记录

?php
$pdo = new PDO( mysql:host=localhost;dbname=user , root , 
for($i=0; $i 1000000; $i++){ $name = substr(md5(time().mt_rand(000,999)),0,10);
 $gender = mt_rand(1,2);
 $sqlstr =  insert into member(name,gender) values(.$name. , .$gender.) 
 $stmt = $pdo- prepare($sqlstr);
 $stmt- execute();
mysql  select count(*) from member;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.23 sec)

3. 当前数据库版本

mysql  select version();
+-----------+
| version() |
+-----------+
| 5.6.24 |
+-----------+
1 row in set (0.01 sec)

分析 offset 过大影响性能的原因

1.offset 较小的情况

mysql  select * from member where gender=1 limit 10,1;
+----+------------+--------+
| id | name | gender |
+----+------------+--------+
| 26 | 509e279687 | 1 |
+----+------------+--------+
1 row in set (0.00 sec)
mysql  select * from member where gender=1 limit 100,1;
+-----+------------+--------+
| id | name | gender |
+-----+------------+--------+
| 211 | 07c4cbca3a | 1 |
+-----+------------+--------+
1 row in set (0.00 sec)
mysql  select * from member where gender=1 limit 1000,1;
+------+------------+--------+
| id | name | gender |
+------+------------+--------+
| 1975 | e95b8b6ca1 | 1 |
+------+------------+--------+
1 row in set (0.00 sec)

当 offset 较小时,查询速度很快,效率较高。 

2.offset 较大的情况

mysql  select * from member where gender=1 limit 100000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 199798 | 540db8c5bc | 1 |
+--------+------------+--------+
1 row in set (0.12 sec)
mysql  select * from member where gender=1 limit 200000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 399649 | 0b21fec4c6 | 1 |
+--------+------------+--------+
1 row in set (0.23 sec)
mysql  select * from member where gender=1 limit 300000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 599465 | f48375bdb8 | 1 |
+--------+------------+--------+
1 row in set (0.31 sec)

当 offset 很大时,会出现效率问题,随着 offset 的增大,执行效率下降。 

分析影响性能原因

select * from member where gender=1 limit 300000,1;

因为数据表是 InnoDB,根据 InnoDB 索引的结构,查询过程为:

通过二级索引查到主键值(找出所有 gender= 1 的 id)。

再根据查到的主键值通过主键索引找到相应的数据块(根据 id 找出对应的数据块内容)。

根据 offset 的值,查询 300001 次主键索引的数据,最后将之前的 300000 条丢弃,取出最后 1 条。

不过既然二级索引已经找到主键值,为什么还需要先用主键索引找到数据块,再根据 offset 的值做偏移处理呢?

如果在找到主键索引后,先执行 offset 偏移处理,跳过 300000 条,再通过第 300001 条记录的主键索引去读取数据块,这样就能提高效率了。

如果我们只查询出主键,看看有什么不同

mysql  select id from member where gender=1 limit 300000,1;
+--------+
| id |
+--------+
| 599465 |
+--------+
1 row in set (0.09 sec)

很明显,如果只查询主键,执行效率对比查询全部字段,有很大的提升。 

推测

只查询主键的情况

因为二级索引已经找到主键值,而查询只需要读取主键,因此 mysql 会先执行 offset 偏移操作,再根据后面的主键索引读取数据块。

需要查询所有字段的情况

因为二级索引只找到主键值,但其他字段的值需要读取数据块才能获取。因此 mysql 会先读出数据块内容,再执行 offset 偏移操作,最后丢弃前面需要跳过的数据,返回后面的数据。 

证实

InnoDB 中有 buffer pool,存放最近访问过的数据页,包括数据页和索引页。

为了测试,先把 mysql 重启,重启后查看 buffer pool 的内容。

mysql  select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in(primary , gender) and TABLE_NAME like  %member%  group by index_name;
Empty set (0.04 sec)

可以看到,重启后,没有访问过任何的数据页。

查询所有字段,再查看 buffer pool 的内容

mysql  select * from member where gender=1 limit 300000,1;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 599465 | f48375bdb8 | 1 |
+--------+------------+--------+
1 row in set (0.38 sec)
mysql  select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in(primary , gender) and TABLE_NAME like  %member%  group by index_name;
+------------+----------+
| index_name | count(*) |
+------------+----------+
| gender | 261 |
| PRIMARY | 1385 |
+------------+----------+
2 rows in set (0.06 sec)

可以看出,此时 buffer pool 中关于 member 表有 1385 个数据页,261 个索引页。 

重启 mysql 清空 buffer pool,继续测试只查询主键

mysql  select id from member where gender=1 limit 300000,1;
+--------+
| id |
+--------+
| 599465 |
+--------+
1 row in set (0.08 sec)
mysql  select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in(primary , gender) and TABLE_NAME like  %member%  group by index_name;
+------------+----------+
| index_name | count(*) |
+------------+----------+
| gender | 263 |
| PRIMARY | 13 |
+------------+----------+
2 rows in set (0.04 sec)

可以看出,此时 buffer pool 中关于 member 表只有 13 个数据页,263 个索引页。因此减少了多次通过主键索引访问数据块的 I / O 操作,提高执行效率。

因此可以证实,mysql 查询时,offset 过大影响性能的原因是多次通过主键索引访问数据块的 I / O 操作。(注意,只有 InnoDB 有这个问题,而 MYISAM 索引结构与 InnoDB 不同,二级索引都是直接指向数据块的,因此没有此问题)。 

InnoDB 与 MyISAM 引擎索引结构对比图

这里写图片描述

优化方法

根据上面的分析,我们知道查询所有字段会导致主键索引多次访问数据块造成的 I / O 操作。

因此我们先查出偏移后的主键,再根据主键索引查询数据块的所有内容即可优化。

mysql  select a.* from member as a inner join (select id from member where gender=1 limit 300000,1) as b on a.id=b.id;
+--------+------------+--------+
| id | name | gender |
+--------+------------+--------+
| 599465 | f48375bdb8 | 1 |
+--------+------------+--------+
1 row in set (0.08 sec)

附:MYSQL limit,offset 区别

SELECT
 keyword
 keyword_rank
WHERE
 advertiserid= 59 
order by
 keyword
LIMIT 2 OFFSET 1;

比如这个 SQL,limit 后面跟的是 2 条数据,offset 后面是从第 1 条开始读取

SELECT
 keyword
 keyword_rank
WHERE
 advertiserid= 59 
ORDER BY
 keyword
LIMIT 2 ,1;

而这个 SQL,limit 后面是从第 2 条开始读,读取 1 条信息。

这两个千万别搞混哦。

感谢你能够认真阅读完这篇文章,希望丸趣 TV 小编分享的“mysql 查询时 offset 过大影响性能的原因是什么”这篇文章对大家有帮助,同时也希望大家多多支持丸趣 TV,关注丸趣 TV 行业资讯频道,更多相关知识等着你来学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-04发表,共计5282字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)
主站蜘蛛池模板: 亚洲白浆 | 无码人妻久久一区二区三区免费丨 | 精品熟人妻一区二区三区四区不卡 | 日本一级淫片bbbxxx | 九色精品视频在线观看 | 国产av激情久久无码天堂 | 欧美性f | a毛片免费观看 | 热久久免费 | 国产人妻大战黑人20p | 久久精品免费观看视频 | 热re久久精品国产99热 | 日韩网红少妇无码视频香港 | 高清一级淫片a级中文字幕 高清一级做a爱过程不卡视频 | 国产精品天天影视久久综合网 | 精品国产乱码一区二区三区 | 亚洲精品成人无码中文毛片 | 欧洲日本一线二线三线区本庄铃 | 中文字幕丰满伦子无码 | a毛片在线还看免费网站 | 少妇人妻偷人精品无码视频新浪 | 亚洲成色www久久网站夜月 | 狠狠色噜噜狠狠狠狠色综合久av | 国产亚洲综合一区二区在线 | 可以免费看毛片的网站 | 中文字幕久热精品视频在线 | 我想看免费毛片 | 日本久久中文字幕精品 | 国产一级第一级毛片 | 亚洲人交乣女bbw | 精品aⅴ一区二区三区 | 青青草在线播放观看 | 国产国产成人精品久久 | 精品一区二区久久 | 国产乱对白精彩 | 国产激情精品一区二区三区 | 视频在线亚洲 | 久久久久人妻精品一区三寸蜜桃 | 亚洲精品第一页 | 久久精品夜夜春 | 国产日韩亚洲不卡高清在线观看 |