Mysql

MySQL - 基於 UUID/created_at 游標的分頁?

  • May 14, 2020

對於大型數據集,使用 an 進行分頁OFFSET是很慢的,並不是最好的分頁方式。更好的分頁方法是使用游標,它只是行上的唯一標識符,因此我們知道從上一個游標位置上次離開的位置繼續分頁的位置。

當涉及到一個自動遞增id值的游標時,它很容易實現:

SELECT * FROM users
WHERE id <= %cursor // cursor is the auto incrementing id, ex. 100000
ORDER BY id DESC
LIMIT %limit

我們不確定的是,如果不是自動遞增id游標,游標的唯一唯一順序標識符是表行上的uuid和。created_at

我們當然可以根據 查詢uuid得到created_at,然後選擇所有users的,<= created_at但問題是如果表中有多個相同created_at時間戳的實例users怎麼辦?知道如何users根據uuid/created_at游標組合查詢表以確保我們獲得正確的數據集(就像我們使用自動遞增一樣id)?同樣,唯一唯一的欄位是uuid因為created_at可能是重複的,但它們的組合每行都是唯一的。

我會回答你的問題,但首先讓我告訴你,我不明白你為什麼要這樣做。自動增量 ID 非常適合此任務。但是使用時間戳列也是正確的,因為依賴 id 進行排序是一種不好的做法。為什麼?因為在某些情況下,它的順序可能不是按時間順序排列的——例如,如果您使用 Galera 集群並且您有故障轉移。

要按照您的要求進行操作,請首先創建此索引:

ALTER TABLE users
   ADD INDEX idx_created_at_uuid (created_at, uuid);

順序列很重要。如果你反轉它,索引將沒有用。

現在您只需要執行這樣的查詢:

SELECT some_columns
   FROM users
   WHERE created_at <= x AND uuid = y
   ORDER BY created_at DESC;

uuid只需要因為 created_at 不是唯一的。如果created_at不是第一列,MySQL 將不得不讀取所有行並將它們複製到臨時表(可以是記憶體中或磁碟上)以對它們進行排序。

如果您決定使用 id,只需保留上述程式碼段,但替換uuidid.

引用自:https://dba.stackexchange.com/questions/205384