以前在數(shù)據(jù)中寫翻頁的代碼時,一直把sql寫成這樣
SELECT * FROM table_name ORDER BY id ASC LIMIT 10 OFFSET 10
也就是用LIMIT
和OFFSET
來控制需要輸出的內(nèi)容區(qū)域,后來我在翻其他人代碼時看到了這種寫法
SELECT * FROM table_name WHERE id > 10 ORDER BY id ASC LIMIT 10
這種寫法是否比前一種寫法的速度要更快,因我看到它使用id主鍵的索引,而且還把檢索區(qū)域用id > 10
縮小了,理論上應(yīng)該更快。但這種寫法應(yīng)該也有一定的局限性,比如最大的局限就是它只能用于那種類似timeline的,從第一頁往后翻的應(yīng)用場景,因為你要翻下一頁必須知道前一頁的最后偏移是多少。
不知道我這樣的分析是否正確,各位有什么樣的看法。
閉關(guān)修行中......
為了方便描述,下面id即指用來排序的字段
使用id > n 的方式,有局限性,但沒有 @qinjianxiang 說的那么大。對于id不連續(xù)的問題,可以通過翻頁的時候同時傳入最后一個id方式來解決。比如:
//輸出時,找出當(dāng)前結(jié)果集中的最大最小id //下一頁 http://example.com/page.php?last=100 select * from table where id<100 order by id desc limit 10 //上一頁 http://example.com/page.php?first=110 select * from table where id>110 order by id desc limit 10
這種方式比較大的缺點(diǎn)是,如果在瀏覽中有插入/刪除操作,翻頁不會更新,而總頁數(shù)可能仍然是根據(jù)新的count(*) 來計算,最終可能會產(chǎn)生某些記錄訪問不到。為了修補(bǔ)這個問題,可以繼續(xù)引入當(dāng)前頁碼以及在上次翻頁以后是否有插入/刪除等影響總記錄數(shù)的操作并進(jìn)行緩存。
MySQL里對LIMIT OFFSET的處理方式是,取出OFFSET+LIMIT的所有數(shù)據(jù),然后去掉OFFSET,返回底部的LIMIT。
所以,在OFFSET數(shù)值較大時,MySQL的查詢性能會非常低。
SELECT * FROM table_name ORDER BY id ASC LIMIT 10 OFFSET 10
MySQL會取出20條數(shù)據(jù),只返回后10條。
SELECT * FROM table_name WHERE id > 10 ORDER BY id ASC LIMIT 10
利用id索引,MySQL只取出10個結(jié)果,返回。這種做法卻是要求連續(xù)翻頁,不能跳頁,受約束。
暫時沒有更好選擇,where id > :id的方式局限性太大,id不一定是連續(xù)的,翻頁也不見得是根據(jù)主鍵來翻。
limit offset從功能上來講是非常好的,如果擔(dān)心offset過大時耗時太長,可以分庫分表?;蛘哂盟阉饕?/p>
樓主的理解是對的。用id>m limit n 比用 limit m,n 快很多,主要原因是limit m,n需要去讀取前面的m條記錄。
如果是翻頁需求,就在返回結(jié)果中取到最后的一個,再傳給下一個鏈接。 @Rodin 給的方案就很好。