分頁
分頁是指在頁面中擷取結果,而不是一次擷取結果;這通常是針對大型結果集完成的,其中會顯示使用者介面,讓使用者流覽至結果的下一頁或上一頁。
警告
不論使用的分頁方法為何,請務必確定您的訂購完全是唯一的。 例如,如果結果只依日期排序,但同一日期可能會有多個結果,則當分頁時,結果在分頁時可能會略過,因為它們在兩個分頁查詢之間以不同方式排序。 依日期和識別碼排序(或任何其他唯一屬性或屬性組合)的排序會讓排序完全是唯一的,並避免此問題。 請注意,關係資料庫預設不會套用任何排序,即使是在主鍵上也一樣。
位移分頁
使用資料庫實作分頁的常見方式是使用 Skip
和 Take
( OFFSET
和 LIMIT
在 SQL 中)。 假設頁面大小為 10 個結果,可以使用 EF Core 擷取第三頁,如下所示:
var position = 20;
var nextPage = context.Posts
.OrderBy(b => b.PostId)
.Skip(position)
.Take(10)
.ToList();
不幸的是,雖然這項技術非常直覺,但它也有一些嚴重的缺點:
- 資料庫仍必須處理前 20 個專案,即使它們未傳回至應用程式也一樣;這會建立可能會大幅計算負載,並隨著略過的資料列數目而增加。
- 如果同時發生任何更新,您的分頁最終可能會略過特定專案或顯示兩次。 例如,如果使用者從第 2 頁移至 3 時移除專案,則整個結果集會「向上移位」,而且會略過一個專案。
索引鍵集分頁
以位移為基礎的分頁的建議替代方案,有時稱為 索引鍵集分頁 或 搜尋型分頁 -- 只是使用 WHERE
子句來略過資料列,而不是位移。 這表示請記住最後一個專案擷取的相關值(而不是其位移),並要求在該資料列之後的下一個資料列。 例如,假設我們擷取的最後一個頁面最後一個專案的識別碼值為 55,我們只需要執行下列動作:
var lastId = 55;
var nextPage = context.Posts
.OrderBy(b => b.PostId)
.Where(b => b.PostId > lastId)
.Take(10)
.ToList();
假設索引是在 上 PostId
定義,此查詢會非常有效率,而且不會區分任何在較低識別碼值中發生的並行變更。
索引鍵集分頁適用于使用者向前和向後巡覽的分頁介面,但不支援隨機存取,使用者可以跳至任何特定頁面。 隨機存取分頁需要使用位移分頁,如上所述;由於位移分頁的缺點,請仔細考慮您的使用案例是否真的需要隨機存取分頁,或下一頁/上一頁導覽是否足夠。 如果需要隨機存取分頁,強固的實作可以在流覽至下一頁/上一頁時使用索引鍵集分頁,並在跳至任何其他頁面時位移流覽。
多個分頁索引鍵
使用索引鍵集分頁時,經常需要依多個屬性排序。 例如,下列查詢會依日期和識別碼分頁:
var lastDate = new DateTime(2020, 1, 1);
var lastId = 55;
var nextPage = context.Posts
.OrderBy(b => b.Date)
.ThenBy(b => b.PostId)
.Where(b => b.Date > lastDate || (b.Date == lastDate && b.PostId > lastId))
.Take(10)
.ToList();
這可確保下一頁會確切地挑選上一個頁面結束的位置。 隨著新增更多排序索引鍵,可以新增其他子句。
注意
大部分的 SQL 資料庫都支援更簡單且更有效率的上述版本,使用 資料列值 : WHERE (Date, Id) > (@lastDate, @lastId)
。 EF Core 目前不支援在 LINQ 查詢中表示此內容,這會由 #26822 追蹤。
索引數
和任何其他查詢一樣,適當的索引編制對於良好的效能至關重要:請務必有對應至您分頁順序的索引。 如果依多個資料行排序,則可以定義這些多個資料行的索引;這稱為 複合式索引 。
如需詳細資訊, 請參閱索引 的檔頁面。
其他資源
- 若要深入瞭解位移型分頁和索引鍵集分頁的缺點, 請參閱這篇文章 。
- .NET 資料社群月臺研討會 ,討論分頁和示範上述所有概念。
- 比較位移和索引鍵集分頁的技術深入探討簡報 。 雖然內容處理 PostgreSQL 資料庫,但一般資訊也適用于其他關係資料庫。
- 如需 EF Core 上簡化索引鍵集分頁的擴充功能,請參閱 MR。EntityFrameworkCore.KeysetPagination 和 MR。AspNetCore.Pagination 。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應