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 | 真經典 - 黎明 | 環球 |
+----------+---------------------------------------------------------+---------------+
但其實使用 OFFSET
和 LIMIT
的話,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
且有序
的欄位,例如id
或created_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)
效能的差異非常顯著。