如何優化limit

2022-08-20 21:54:11 字數 2073 閱讀 5577

假設有如下sql語句:

select * from table1 limit offset, rows

這是一條典型的limit語句,常見的使用場景是,某些查詢返回的內容特別多,而客戶端處理能力有限,希望每次只取一部分結果進行處理。

上述sql語句的實現機制是:

從「table」表中讀取offset+rows行記錄

拋棄前面的offset行記錄,返回後面的rows行記錄作為最終結果。

這種實現機制存在乙個弊端:雖然只需要返回rows行記錄,但卻必須先訪問offset行不會用到的記錄。對一張資料量很大的表進行查詢時,offset值可能非常大,此時limit語句的效率就非常低了。

假設表message表中有10萬行記錄,每次取1000條。

優化前:

select message.* from message limit 0,1000

select message.* from message limit 1000,1000

select message.* from message limit 2000,1000

……select message.* from message limit 998000,1000

select message.* from message limit 999000,1000

優化後(利用自增主鍵,避免offset的使用):

select message.* from message where uid>0 limit 1000

select message.* from message where uid>1000 limit 1000

select message.* from message where uid>2000 limit 1000

……select message.* from message where uid>998000 limit 1000

select message.* from message where uid>999000 limit 1000

在筆者的機器上,優化前,sql語句從前往後越來越慢(最後一條語句執行了150毫秒),而優化後,每條語句的耗時都是微妙級的。

實際工程中遇到的查詢,通常要複雜些,比如,多表查詢、條件查詢。這種情況下,查詢結果通常不是按照自增主鍵的順序逐一排列的。

例如,對於下述sql語句,就不能像第二節那樣優化了:

select timerec from message where evttype = 1 and nodename = 'node1'

limit 0,1000

……select timerec from message where evttype = 1 and nodename = 'node1'

limit 999000,1000

……

優化方案:建立臨時表(含自增主鍵)儲存數十萬行的查詢結果,之後用第二節的方法分多次訪問臨時表、獲取資料。

建立臨時表

create temporary table tmp_timerec(

`uid` bigint(20) not null auto_increment,

`timerec` datetime not null,

primary key (`uid`))

插入查詢結果到臨時表

insert into tmp_timerec

select null,timerec from message

where evttype = 1 and nodename = 『node1』

分多次查詢臨時表

select timerec from tmp_timerec where uid > 0 limit 1000

……select timerec from tmp_timerec where uid > 999000 limit 1000

如何優化limit

當乙個資料庫表過於龐大,limit offset,length中的offset值過大,則sql查詢語句會非常緩慢,你需增加order by,並且order by欄位需要建立索引。如果使用子查詢去優化limit的話,則子查詢必須是連續的,某種意義來講,子查詢不應該有where條件,where會過濾資料...

查詢 limit優化

一種情況,limit接受乙個引數,即是返回記錄的前面最大行數 另一情況,limit接受兩個引數,乙個是返回記錄行的偏移量,乙個是返回記錄行的最大數量 用法1 limit rows select from user order by id limit 5 返回記錄的前5行。用法2 limit offs...

limit分頁優化

對於有大資料量的mysql表來說,使用limit分頁存在很嚴重的效能問題。查詢從第1000000之後的30條記錄 sql 1 平均用時6.6秒 select from cdb posts order by pid limit 1000000 30 sql 2 平均用時0.6秒 select from...