麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 數(shù)據(jù)庫 > MySQL > 正文

mysql查詢時(shí)offset過大影響性能的原因和優(yōu)化詳解

2024-07-25 19:08:31
字體:
供稿:網(wǎng)友

前言

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

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

<?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.當(dāng)前數(shù)據(jù)庫版本

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)

當(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í),會(huì)出現(xiàn)效率問題,隨著offset的增大,執(zhí)行效率下降。 

分析影響性能原因

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

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

  • 通過二級(jí)索引查到主鍵值(找出所有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í)索引已經(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)孔侄危泻艽蟮奶嵘?nbsp; 

推測

只查詢主鍵的情況 

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

需要查詢所有字段的情況 

因?yàn)槎?jí)索引只找到主鍵值,但其他字段的值需要讀取數(shù)據(jù)塊才能獲取。因此mysql會(huì)先讀出數(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不同,二級(jí)索引都是直接指向數(shù)據(jù)塊的,因此沒有此問題 )。 

InnoDB與MyISAM引擎索引結(jié)構(gòu)對比圖

這里寫圖片描述

mysql,查詢,offset,性能

優(yōu)化方法

根據(jù)上面的分析,我們知道查詢所有字段會(huì)導(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)

附:MYSQL limit,offset 區(qū)別

SELECT  keywordFROM  keyword_rankWHERE  advertiserid='59'order by  keywordLIMIT 2 OFFSET 1;

比如這個(gè)SQL ,limit后面跟的是2條數(shù)據(jù),offset后面是從第1條開始讀取

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

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

這兩個(gè)千萬別搞混哦。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請移步到MYSQL教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 精国品产一区二区三区有限公司 | 特大黑人videos与另类娇小 | 国产乱淫av | 日韩在线欧美在线 | 日韩精品久久久久久久电影99爱 | 丁香天堂网 | 在线看一区二区三区 | 精品无吗乱吗av国产爱色 | 性欧美大战久久久久久久免费观看 | xxxx18韩国护士hd老师 | 国产亚洲精品综合一区91 | 日韩黄色精品视频 | 夜夜看 | 精品国产一区二区三区四区在线 | 久久久久北条麻妃免费看 | 久久精品国产99久久6动漫亮点 | 毛片视频网站 | 法国极品成人h版 | 夜添久久精品亚洲国产精品 | 色综合久久99 | 午夜视频在线观看免费视频 | 婷婷久久影院 | 曰韩毛片| 亚洲综合精品 | 国产一区二区午夜 | 一级成人免费 | 精品人成 | 热re91久久精品国产99热 | 日本中文字幕久久 | 一级黄色在线免费观看 | 女18一级大黄毛片免费女人 | 欧美日韩在线播放一区 | 国产精品免费大片 | 日韩精品一区二区三区中文 | 亚洲精品tv久久久久久久久久 | 今井夏帆av一区二区 | 日本不卡一二三区 | 国产精品视频一区二区三区四 | 一级黄色免费大片 | 国产精品久久久久久久久久久久久久久久 | 久久久久久久亚洲精品 |