為什麼不該用 offset & limit 來做 pagination

常會用見到有人用這段 sql 來做 pagination:

SQL SELECT * FROM table_name LIMIT 10 OFFSET 40

但這段 code 只應該出現在 MVP,或是 row 很少的 table 中。

主要問題是因為他會產生 Full Table Scan (aka Sequential Scan),which is slow(因為 I/O 很慢)

換句話說,本來想要讀 500001 ~ 500020 的這 20 筆資料,上面的語句卻要先掃過 500000 筆根本不是所求的資料,這十分沒效率。

The higher your OFFSET, the longer the query will take.

Instead, 應該要這樣做:

SQL SELECT * FROM table_name where id > 10 limit 20

這個叫做 cursor based pagination。

local 不該保留 offset,取而代之的,應該要保留最後要求的 Primary Key(id 之類的)

不過若要能做到這招,就需要 unique, sequential 的欄位,像是 unique integer ID 或 timestamp,這在某些情況下可能不樂見,就需要權衡。

Ref