2 回答

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超13個贊
請記住,確實(shí)的查詢LIMIT 500000, 1000
必須掃描 501,000 行才能獲得最后 1000 行。LIMIT 按位置而不是按值選擇行。所以沒有辦法使用索引直接跳到你想要的行。因此,它必須從第一行開始,讀取所有行,直到超過您要求的偏移量。
因此,重復(fù)地對具有連續(xù)偏移量的行集進(jìn)行分頁非常昂貴,因?yàn)槊總€下一個查詢都必須重新讀取它之前已經(jīng)讀取的數(shù)千行。它基本上是一個 O(n 2 ) 算法。
PS:這行不通:LIMIT ?*1000, 1000
因?yàn)?LIMIT 不接受表達(dá)式。它只需要整數(shù)文字或占位符。在傳遞值之前,您必須LIMIT ?, 1000
在 Go 代碼中進(jìn)行乘法運(yùn)算。

TA貢獻(xiàn)1784條經(jīng)驗(yàn) 獲得超8個贊
正如比爾在他的回答中提到的,OFFSET 查詢有充分的缺點(diǎn)。
就數(shù)據(jù)庫而言,使用單個查詢選擇所有內(nèi)容是快速的,但如果您不快速處理返回的行,它會長時間使用數(shù)據(jù)庫連接,使其無法用于其他任何人。這在繁忙的服務(wù)器中可能是一個問題,其中空閑的數(shù)據(jù)庫連接通常是稀缺資源。
您(可能)錯過了沒有這些缺點(diǎn)的第三個選項(xiàng):鍵集分頁(又名尋求分頁)。如果 foo 至少有一個 UNIQUE NOT NULL 列(即一個主鍵),并且 created 被索引,則此方法有效。
鍵集分頁在整個網(wǎng)絡(luò)上都有很好的解釋,但簡而言之(假設(shè) foo 有一個名為“id”的 UNIQUE NOT NULL 列):
SELECT *
FROM foo
LEFT JOIN ... ON ... -- multiple times
WHERE (foo.created = X AND foo.id > Y) OR foo.created > X
ORDER BY foo.created, foo.id
LIMIT 1000
這里,X 和 Y 分別是上一個查詢中最后一行的 created 和 id 列的值(省略第一個查詢中的 WHERE 子句)。
這樣,您可以在恒定時間內(nèi)檢索連續(xù)的頁面。根據(jù)將行插入 foo 或任何連接表的方式,執(zhí)行此操作時可能會丟失行或獲得重復(fù)的行(與 OFFSET 相同)。如果這不是一個選項(xiàng),您必須堅(jiān)持一個查詢。
- 2 回答
- 0 關(guān)注
- 132 瀏覽
添加回答
舉報(bào)