最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2018年06月13日 09:26:53   作者:傲雪星楓  
這篇文章主要給大家介紹了關(guān)于mysql查詢時offset過大影響性能的原因和優(yōu)化的相關(guān)資料,并在文末跟大家分享了MYSQL中l(wèi)imit,offset的區(qū)別,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習學(xué)習吧

前言

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

準備測試數(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.當前數(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)

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

分析影響性能原因

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

因為數(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)孔侄?,有很大的提升?nbsp; 

推測

只查詢主鍵的情況

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

需要查詢所有字段的情況

因為二級索引只找到主鍵值,但其他字段的值需要讀取數(shù)據(jù)塊才能獲取。因此mysql會先讀出數(shù)據(jù)塊內(nèi)容,再執(zhí)行offset偏移操作,最后丟棄前面需要跳過的數(shù)據(jù),返回后面的數(shù)據(jù)。 

證實

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)

可以看出,此時buffer pool中關(guān)于member表有1385個數(shù)據(jù)頁,261個索引頁。 

重啟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)

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

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

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

這里寫圖片描述

優(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)

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

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

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

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

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

這兩個千萬別搞混哦。

總結(jié)

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

相關(guān)文章

  • mysql數(shù)據(jù)庫基本語法及操作大全

    mysql數(shù)據(jù)庫基本語法及操作大全

    這篇文章主要介紹了mysql數(shù)據(jù)庫基本語法及操作大全,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • 詳解數(shù)據(jù)庫語言中的null值

    詳解數(shù)據(jù)庫語言中的null值

    這篇文章主要詳解了數(shù)據(jù)庫語言中的null值,針對MySQL上的實例進行講解,需要的朋友可以參考下
    2015-04-04
  • MySQL定時器EVENT學(xué)習筆記

    MySQL定時器EVENT學(xué)習筆記

    本文為大家介紹下MySQL定時器EVENT,要使定時起作用 MySQL的常量GLOBAL event_scheduler必須為on或者是1,感興趣的朋友可以了解下
    2013-11-11
  • MySQL的order?by如何避免"未命中索引"(推薦)

    MySQL的order?by如何避免"未命中索引"(推薦)

    本文詳細解析了在使用MySQL的OrderBy語句時,如何通過Explain查看執(zhí)行計劃以及如何有效利用索引,介紹了常見的索引未命中情況,提供了多個示例來解釋如何根據(jù)索引的不同使用情況調(diào)整SQL語句,以確保最優(yōu)的查詢性能
    2024-11-11
  • MySQL Antelope和Barracuda的區(qū)別分析

    MySQL Antelope和Barracuda的區(qū)別分析

    這篇文章主要介紹了MySQL Antelope和Barracuda的區(qū)別分析,Antelope和Barracude都是一種文件格式,需要的朋友可以參考下
    2014-07-07
  • 關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解

    關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解

    本文主要講解了關(guān)于MySQL的存儲函數(shù)(自定義函數(shù))的定義和使用方法詳解與存儲函數(shù)與存儲過程的區(qū)別
    2018-03-03
  • MAC下MySQL忘記初始密碼怎么辦

    MAC下MySQL忘記初始密碼怎么辦

    MySQL初始密碼忘記怎么辦,這篇文章主要介紹了MAC下MySQL忘記初始密碼的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • MYsql庫與表的管理及視圖介紹

    MYsql庫與表的管理及視圖介紹

    這篇文章主要介紹了MYsql庫與表的管理及視圖介紹,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • MySQL慢查詢開啟與優(yōu)化指南

    MySQL慢查詢開啟與優(yōu)化指南

    文章主要介紹了慢查詢?nèi)罩驹贛ySQL中的應(yīng)用,包括其定義、開啟方式、參數(shù)解析及分析工具,通過案例詳細講解了如何通過慢查詢?nèi)罩径ㄎ缓蛢?yōu)化性能瓶頸,如索引失效、隱式類型轉(zhuǎn)換等問題,并給出了生產(chǎn)環(huán)境的最佳實踐及學(xué)習建議,需要的朋友可以參考下
    2026-03-03
  • Mysql中InnoDB與MyISAM索引差異詳解(最新整理)

    Mysql中InnoDB與MyISAM索引差異詳解(最新整理)

    InnoDB和MyISAM在索引實現(xiàn)和特性上有差異,包括聚集索引、非聚集索引、事務(wù)支持、并發(fā)控制、覆蓋索引、主鍵約束、外鍵支持和物理存儲結(jié)構(gòu)等方面,InnoDB更適合事務(wù)型應(yīng)用,而MyISAM適合只讀或讀多寫少的場景,本文介紹Mysql中InnoDB與MyISAM索引差異,感興趣的朋友一起看看吧
    2025-03-03

最新評論

鹿邑县| 漳州市| 大丰市| 通州区| 星子县| 新宾| 札达县| 临潭县| 诸城市| 东平县| 正镶白旗| 嘉鱼县| 富蕴县| 阳新县| 来安县| 七台河市| 成武县| 沅江市| 九寨沟县| 雷州市| 鹿邑县| 巴中市| 大关县| 青州市| 富川| 察雅县| 鄂州市| 清镇市| 灌南县| 千阳县| 万年县| 遵义市| 寿宁县| 黄骅市| 阳山县| 英山县| 共和县| 合山市| 维西| 颍上县| 芦山县|