MySQL的limit用法和分页查询的性能分析及优化
一、limit用法
在我們使用查詢語句的時(shí)候,經(jīng)常要返回前幾條或者中間某幾行數(shù)據(jù),這個(gè)時(shí)候怎么辦呢?不用擔(dān)心,mysql已經(jīng)為我們提供了這樣一個(gè)功能。
SELECT * FROM table LIMIT [offset,] rows | `rows OFFSET offset ` (LIMIT offset, `length`) SELECT * FROM table where condition1 = 0 and condition2 = 0 and condition3 = -1 and condition4 = -1 order by id asc LIMIT 2000 OFFSET 50000LIMIT 子句可以被用于強(qiáng)制 SELECT 語句返回指定的記錄數(shù)。LIMIT 接受一個(gè)或兩個(gè)數(shù)字參數(shù)。參數(shù)必須是一個(gè)整數(shù)常量。如果給定兩個(gè)參數(shù),第一個(gè)參數(shù)指定第一個(gè)返回記錄行的偏移量,第二個(gè)參數(shù)指定返回記錄行的最大數(shù)目。初始記錄行的偏移量是 0(而不是 1): 為了與 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15//為了檢索從某一個(gè)偏移量到記錄集的結(jié)束所有的記錄行,可以指定第二個(gè)參數(shù)為 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.//如果只給定一個(gè)參數(shù),它表示返回最大的記錄行數(shù)目:
mysql> SELECT * FROM table LIMIT 5;?//檢索前 5 個(gè)記錄行
//換句話說,LIMIT n?等價(jià)于?LIMIT 0,n。
二、Mysql的分頁查詢語句的性能分析
MySql分頁sql語句,如果和MSSQL的TOP語法相比,那么MySQL的LIMIT語法要顯得優(yōu)雅了許多。使用它來分頁是再自然不過的事情了。
最基本的分頁方式:
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT ...在中小數(shù)據(jù)量的情況下,這樣的SQL足夠用了,唯一需要注意的問題就是確保使用了索引:
舉例來說,如果實(shí)際SQL類似下面語句,那么在category_id, id兩列上建立復(fù)合索引比較好:
子查詢的分頁方式:
隨著數(shù)據(jù)量的增加,頁數(shù)會(huì)越來越多,查看后幾頁的SQL就可能類似:
SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 10000, 10
一言以蔽之,就是越往后分頁,LIMIT語句的偏移量就會(huì)越大,速度也會(huì)明顯變慢。
此時(shí),我們可以通過子查詢的方式來提高分頁效率,大致如下:
JOIN分頁方式
SELECT * FROM `content` AS t1 JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2 WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;經(jīng)過我的測(cè)試,join分頁和子查詢分頁的效率基本在一個(gè)等級(jí)上,消耗的時(shí)間也基本一致。
explain SQL語句:
為什么會(huì)這樣呢?因?yàn)樽硬樵兪窃谒饕贤瓿傻?#xff0c;而普通的查詢時(shí)在數(shù)據(jù)文件上完成的,通常來說,索引文件要比數(shù)據(jù)文件小得多,所以操作起來也會(huì)更有效率。
實(shí)際可以利用類似策略模式的方式去處理分頁,比如判斷如果是一百頁以內(nèi),就使用最基本的分頁方式,大于一百頁,則使用子查詢的分頁方式。
三、對(duì)于有大數(shù)據(jù)量的mysql表來說,使用LIMIT分頁存在很嚴(yán)重的性能問題。
查詢從第1000000之后的30條記錄:
SQL代碼1:平均用時(shí)6.6秒 SELECT * FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 30SQL代碼2:平均用時(shí)0.6秒 SELECT * FROM `cdb_posts` WHERE pid >= (SELECT pid FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 1) LIMIT 30因?yàn)橐?strong>取出所有字段內(nèi)容,第一種需要跨越大量數(shù)據(jù)塊并取出,而第二種基本通過直接根據(jù)索引字段定位后,才取出相應(yīng)內(nèi)容,效率自然大大提升。對(duì)limit的優(yōu)化,不是直接使用limit,而是首先獲取到offset的id,然后直接使用limit size來獲取數(shù)據(jù)。
可以看出,越往后分頁,LIMIT語句的偏移量就會(huì)越大,兩者速度差距也會(huì)越明顯。
實(shí)際應(yīng)用中,可以利用類似策略模式的方式去處理分頁,比如判斷如果是一百頁以內(nèi),就使用最基本的分頁方式,大于一百頁,則使用子查詢的分頁方式。
優(yōu)化思想:避免數(shù)據(jù)量大時(shí)掃描過多的記錄
為了保證index索引列連續(xù),可以為每個(gè)表加一個(gè)自增字段,并且加上索引
參考:mysql分頁offset過大,Sql優(yōu)化經(jīng)驗(yàn)
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的MySQL的limit用法和分页查询的性能分析及优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx - request_time
- 下一篇: MySQL 优化之 index merg