亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

mysql查詢時offset過大影響性能的原因和優化詳解

2024-07-25 19:08:31
字體:
來源:轉載
供稿:網友

前言

mysql查詢使用select命令,配合limit,offset參數可以讀取指定范圍的記錄。本文將介紹mysql查詢時,offset過大影響性能的原因及優化方法。

準備測試數據表及數據

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引擎索引結構對比圖

這里寫圖片描述

mysql,查詢,offset,性能

優化方法

根據上面的分析,我們知道查詢所有字段會導致主鍵索引多次訪問數據塊造成的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  keywordFROM  keyword_rankWHERE  advertiserid='59'order by  keywordLIMIT 2 OFFSET 1;

比如這個SQL ,limit后面跟的是2條數據,offset后面是從第1條開始讀取

SELECT  keywordFROM  keyword_rankWHERE  advertiserid='59'ORDER BY  keywordLIMIT 2 ,1;

而這個SQL,limit后面是從第2條開始讀,讀取1條信息。

這兩個千萬別搞混哦。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久手机精品视频| 97国产精品视频| 久久久久中文字幕2018| 91精品啪在线观看麻豆免费| 精品视频久久久久久| 国产亚洲一区二区精品| 永久免费毛片在线播放不卡| 成人国产精品久久久| 九九热精品视频| 欧美性猛交xxxx免费看久久久| 国产精品成人一区| 国产成人a亚洲精品| 亚洲日本欧美中文幕| 日产精品久久久一区二区福利| 欧美性高跟鞋xxxxhd| 国产美女精品免费电影| 丁香五六月婷婷久久激情| 欧美激情国产精品| 成人免费激情视频| yellow中文字幕久久| 夜夜嗨av一区二区三区四区| 久久国产精品亚洲| 2019中文字幕在线观看| 日韩在线视频观看正片免费网站| 国产深夜精品福利| 欧美日韩成人免费| 亚洲国产精品专区久久| 亚洲激情在线观看视频免费| 在线播放精品一区二区三区| 久久人人爽人人爽爽久久| 亚洲国产一区二区三区在线观看| 欧美激情一级二级| 亚洲欧美资源在线| 久久久久久一区二区三区| 欧美精品一区三区| 91在线精品播放| 成人精品在线观看| 欧美日韩国产精品一区二区不卡中文| 777国产偷窥盗摄精品视频| 国产在线不卡精品| 97**国产露脸精品国产| 色综合久久久久久中文网| 久久久久久久久中文字幕| 国产成人精品一区二区在线| 国产精品久久二区| 亚洲一区亚洲二区亚洲三区| 亚洲sss综合天堂久久| 久久久久免费视频| 欧美精品18videos性欧美| 久久久久久久久久久av| 国产一区av在线| 国产精品视频在线播放| 亚洲性生活视频在线观看| 久久免费国产视频| 欧美激情精品久久久久久大尺度| 日韩精品视频免费| 国产亚洲精品综合一区91| 91色在线观看| 欧美视频国产精品| 久久亚洲国产精品成人av秋霞| 国产视频在线观看一区二区| 97色在线观看免费视频| 精品亚洲国产成av人片传媒| 久久99久久99精品免观看粉嫩| 国产视频久久久久| 亚洲人成网站777色婷婷| 91色在线观看| 法国裸体一区二区| 久久电影一区二区| 欧美丰满少妇xxxxx做受| 国产精品久久视频| 日韩有码片在线观看| 久久99久国产精品黄毛片入口| 成人国产亚洲精品a区天堂华泰| 国产欧美精品xxxx另类| 欧美中文在线视频| 免费97视频在线精品国自产拍| 日韩精品福利网站| 日本国产欧美一区二区三区| 91夜夜揉人人捏人人添红杏| 国产91ⅴ在线精品免费观看| 日韩精品免费一线在线观看| 国产精品日韩在线播放| 欧美成人三级视频网站| 亚洲乱码av中文一区二区| 国产精品视频一| 国产一区二区欧美日韩| 欧美精品在线极品| 国产精品一区二区久久久久| 中文综合在线观看| 欧美一级视频免费在线观看| 欧美精品在线观看| 日韩精品亚洲视频| 波霸ol色综合久久| 亚洲毛茸茸少妇高潮呻吟| 久久综合久久美利坚合众国| 国产成人福利夜色影视| 北条麻妃久久精品| 欧美成人高清视频| 精品成人av一区| 欧美一级黑人aaaaaaa做受| 欧美精品午夜视频| 亚洲午夜小视频| 亚洲激情视频在线| 成人444kkkk在线观看| 中文字幕不卡在线视频极品| 国产成人精品一区二区在线| 成人网欧美在线视频| 日韩av影视在线| 日韩电影免费观看在线| 国产精品电影网站| 成人午夜一级二级三级| 91麻豆国产精品| 午夜欧美大片免费观看| 精品久久久久久久久久ntr影视| 亚洲成人a级网| 亚洲三级 欧美三级| 国产精品18久久久久久首页狼| 性欧美xxxx视频在线观看| 97欧美精品一区二区三区| 在线视频免费一区二区| 亚洲免费视频一区二区| 欧美多人乱p欧美4p久久| 欧美性开放视频| 一区国产精品视频| 国产美女精品视频| 美日韩精品免费视频| 欧美麻豆久久久久久中文| 97香蕉超级碰碰久久免费软件| 成人午夜激情免费视频| 91tv亚洲精品香蕉国产一区7ujn| 国产精品久久久久久久久免费看| 久久久91精品国产一区不卡| 中文字幕在线观看亚洲| 色偷偷噜噜噜亚洲男人的天堂| 亚洲欧美综合区自拍另类| 国产精品成人v| 亚洲成人在线视频播放| 国产在线高清精品| 日韩精品亚洲视频| 亚洲网站视频福利| 狠狠操狠狠色综合网| 日韩av在线最新| 欧美一区亚洲一区| 亚洲欧美综合另类中字| 久久免费少妇高潮久久精品99| 国产福利精品视频| 在线a欧美视频| 欧美性受xxx| 中文字幕国产精品| 亚洲精品久久久久久久久| 自拍视频国产精品| 欧美极品在线视频| 91夜夜未满十八勿入爽爽影院| 日韩精品中文字幕在线| 国产免费一区二区三区在线观看| 日韩av在线网站| 国产国语刺激对白av不卡| 国产精品黄页免费高清在线观看| 欧美精品18videosex性欧美| 亚洲视频专区在线| 日韩欧美有码在线| 亚洲最大福利视频网| 97香蕉久久夜色精品国产|