假設有如下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...