您無法知道給定頁面上的第一個ID是什麼,因爲ID號碼不一定是順序的。換句話說,序列中可能存在空白,所以100行的第五頁上的行不一定從id 500開始。它可以以id 527開始,例如,不可能知道。
換言之另一種方式:ID是一個值,而不是行號。
如果你的客戶是通過以升序頁推進一個可行的辦法是,每個REST請求獲取數據,指出值頁面上的最大 ID,然後使用該在下一個 REST請求,以便它查詢id值較大。
SELECT ... FROM ... WHERE filterKey = filterValue
AND id > id_of_last_match_of_previous_page
但是,如果您的REST請求可以獲取任意隨機頁面,則此解決方案不起作用。這取決於已經獲取了先前的頁面。
另一種解決方案是使用LIMIT <x> OFFSET <y>
語法。這使您可以請求任何任意頁面。 LIMIT <y>, <x>
的工作原理是相同的,但出於某種原因,x和y在兩種不同的語法形式中是相反的,所以請牢記這一點。
使用LIMIT...OFFSET
在請求結果中包含多頁的頁面時效率不高。假設您要求第5,000頁。 MySQL必須在5,000頁的服務器端生成一個結果,然後丟棄其中的4,999個,並返回結果中的最後一頁。對不起,但這是它的工作原理。
回覆您的評論:
你必須明白,WHERE
適用於值行的條件,但網頁是由行位置定義。這是確定行的兩種不同方式!
如果您有一列保證爲行號,那麼您可以像使用行位置那樣使用該值。您甚至可以在其上放置索引,或將其用作主鍵。
但是,主鍵值可能會更改,並且可能不連續,例如,如果更新或刪除行或回滾某些事務等等。對主鍵值重新編號是一個壞主意,因爲其他表或外部數據可能會引用主鍵值。
所以你可以添加另一列而不是的主鍵,但只有一個行號。
ALTER TABLE MyTable ADD COLUMN row_number BIGINT UNSIGNED, ADD KEY (row_number);
然後在需要對行重新編號時填寫值。
SET @row := 0;
UPDATE MyTable SET row_number = (@row := @row + 1) ORDER BY id;
例如,如果您曾刪除某些行,您將不得不重新編號行。經常這樣做效率不高,取決於表格的大小。
另外,如果不鎖定表格,新插入無法創建正確的行號值。這對於防止競爭條件是必要的。
如果您保證row_number
是一系列連續值,那麼它既是一個值又是一個行位置,因此您可以將它用於任何任意行的頁面的高性能索引查找。
SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;
至少直到下一次通過刪除或新插入對行號序列置疑。
這似乎是一個非常奇怪的方式來做到這一點。在我的經驗研究小型/中型數據集標準是爲了通過行,這樣就得到一個一致的數據集(這樣你就可以使用任何WHERE),然後使用LIMIT和,位我懷疑你可能已經錯過了,偏移子句告訴MySQL從位置X返回行。 –
過濾的數據集通常可能有多大? – Strawberry
喬恩 - 我明白了,我不熟悉OFFSET,謝謝。草莓 - 我希望能夠一次獲取200行的東西,從過濾的結果可以達到成千上萬。 –