真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

mysql查詢時(shí),offset過大影響性能怎么處理

本文主要給大家介紹MySQL查詢時(shí),offset過大影響性能怎么處理,文章內(nèi)容都是筆者用心摘選和編輯的,具有一定的針對性,對大家的參考意義還是比較大的,下面跟筆者一起了解下mysql查詢時(shí),offset過大影響性能怎么處理吧。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),景洪企業(yè)網(wǎng)站建設(shè),景洪品牌網(wǎng)站建設(shè),網(wǎng)站定制,景洪網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,景洪網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

準(zhǔn)備測試數(shù)據(jù)表及數(shù)據(jù)

1.創(chuàng)建表

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條記錄

prepare($sqlstr);    $stmt->execute();}
?>mysql> select count(*) from member;
+----------+| count(*) |
+----------+|  1000000 |
+----------+1 row in set (0.23 sec)


3.當(dāng)前數(shù)據(jù)庫版本

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

mysql查詢時(shí),offset過大影響性能怎么處理

分析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)

當(dāng)offset較小時(shí),查詢速度很快,效率較高。
 
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)

當(dāng)offset很大時(shí),會出現(xiàn)效率問題,隨著offset的增大,執(zhí)行效率下降。

分析影響性能原因

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

因?yàn)閿?shù)據(jù)表是InnoDB,根據(jù)InnoDB索引的結(jié)構(gòu),查詢過程為:

  • 通過二級索引查到主鍵值(找出所有g(shù)ender=1的id)。

  • 再根據(jù)查到的主鍵值通過主鍵索引找到相應(yīng)的數(shù)據(jù)塊(根據(jù)id找出對應(yīng)的數(shù)據(jù)塊內(nèi)容)。

  • 根據(jù)offset的值,查詢300001次主鍵索引的數(shù)據(jù),最后將之前的300000條丟棄,取出最后1條。

不過既然二級索引已經(jīng)找到主鍵值,為什么還需要先用主鍵索引找到數(shù)據(jù)塊,再根據(jù)offset的值做偏移處理呢?

如果在找到主鍵索引后,先執(zhí)行offset偏移處理,跳過300000條,再通過第300001條記錄的主鍵索引去讀取數(shù)據(jù)塊,這樣就能提高效率了。

如果我們只查詢出主鍵,看看有什么不同

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

很明顯,如果只查詢主鍵,執(zhí)行效率對比查詢?nèi)孔侄?,有很大的提升?/p>

推測

只查詢主鍵的情況
因?yàn)槎壦饕呀?jīng)找到主鍵值,而查詢只需要讀取主鍵,因此mysql會先執(zhí)行offset偏移操作,再根據(jù)后面的主鍵索引讀取數(shù)據(jù)塊。

需要查詢所有字段的情況
因?yàn)槎壦饕徽业街麈I值,但其他字段的值需要讀取數(shù)據(jù)塊才能獲取。因此mysql會先讀出數(shù)據(jù)塊內(nèi)容,再執(zhí)行offset偏移操作,最后丟棄前面需要跳過的數(shù)據(jù),返回后面的數(shù)據(jù)。

證實(shí)

InnoDB中有buffer pool,存放最近訪問過的數(shù)據(jù)頁,包括數(shù)據(jù)頁和索引頁。

為了測試,先把mysql重啟,重啟后查看buffer pool的內(nèi)容。

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)

可以看到,重啟后,沒有訪問過任何的數(shù)據(jù)頁。

查詢所有字段,再查看buffer pool的內(nèi)容

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)

可以看出,此時(shí)buffer pool中關(guān)于member表有1385個(gè)數(shù)據(jù)頁,261個(gè)索引頁。
 
重啟mysql清空buffer pool,繼續(xù)測試只查詢主鍵

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)

可以看出,此時(shí)buffer pool中關(guān)于member表只有13個(gè)數(shù)據(jù)頁,263個(gè)索引頁。因此減少了多次通過主鍵索引訪問數(shù)據(jù)塊的I/O操作,提高執(zhí)行效率。

因此可以證實(shí),mysql查詢時(shí),offset過大影響性能的原因是多次通過主鍵索引訪問數(shù)據(jù)塊的I/O操作。(注意,只有InnoDB有這個(gè)問題,而MYISAM索引結(jié)構(gòu)與InnoDB不同,二級索引都是直接指向數(shù)據(jù)塊的,因此沒有此問題 )。
 
InnoDB與MyISAM引擎索引結(jié)構(gòu)對比圖

mysql查詢時(shí),offset過大影響性能怎么處理

優(yōu)化方法

根據(jù)上面的分析,我們知道查詢所有字段會導(dǎo)致主鍵索引多次訪問數(shù)據(jù)塊造成的I/O操作。

因此我們先查出偏移后的主鍵,再根據(jù)主鍵索引查詢數(shù)據(jù)塊的所有內(nèi)容即可優(yōu)化。

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)

看完以上關(guān)于mysql查詢時(shí),offset過大影響性能怎么處理,很多讀者朋友肯定多少有一定的了解,如需獲取更多的行業(yè)知識信息 ,可以持續(xù)關(guān)注我們的行業(yè)資訊欄目的。


標(biāo)題名稱:mysql查詢時(shí),offset過大影響性能怎么處理
URL鏈接:http://weahome.cn/article/pdgdcd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部