Cursor-based Pagination

分頁(Pagination) 是在製作 Dashboard 過程中一定會需要的功能。

Traditional Approach

在傳統方法中,大多數開發者都會習慣使用 OFFSET 搭配 LIMIT 去處理分頁。

例如:

SELECT album_id, album_name, album_company FROM album ORDER BY album_id LIMIT 10 OFFSET 60;
+----------+---------------------------------------------------------+---------------+
| album_id | album_name                                              | album_company |
+----------+---------------------------------------------------------+---------------+
|      292 | 同名專輯                                                | 環球          |
|      297 | 正東 10 X 10 我至愛唱片  - 許志安『爛泥』                 | 環球          |
|      299 | 黑白                                                    | 環球          |
|      301 | 默契                                                    | 環球          |
|      302 | 忘了                                                    | 華納          |
|      305 | Belong To Myself                                        | 環球          |
|      307 | 快樂為主                                                | 環球          |
|      310 | KELLY CHEN BPM DANCE COLLECTION VOLUME 4                | 環球          |
|      311 | 就是陳潔儀新加坡演唱會                                   | 海蝶          |
|      318 | 真經典 - 黎明                                           | 環球          |
+----------+---------------------------------------------------------+---------------+

但其實使用 OFFSETLIMIT 的話,Database 的運作是從頭到尾的走訪,也就是所謂的 Scan Table。只要進到很末端的頁數,就會讓 Database 非常忙碌、緩慢,甚至可能會有倒站的風險。

比方說,如果要從第 10000000 往下找 10 筆,就必須走訪 10000010 筆資料。

SELECT album_id, album_name, album_company FROM album ORDER BY album_id LIMIT 10 OFFSET 10000000;
10 rows in set (14.72 sec)

Cursor-based Pagination

Cursor-based Pagination 是透過明確的起始點去定位,因此需要有一些先決條件:

  • Cursor 必須基於一個 有 index有序 的欄位,例如 idcreated_at
  • 沒有頁數概念

album_id 當定位點為例,在前端的每一頁,都必須紀錄該頁的最後一個 album_id

所以要從第 10000000 往下找 10 筆就變成:

SELECT album_id, album_name, album_company FROM album WHERE album_id > 10000000 ORDER BY album_id LIMIT 10;
10 rows in set (0.00 sec)

效能的差異非常顯著。

Categories: Database