EFCore性能优化方案-分页

偏移分页

使用数据库实现分页的一种常见方法是使用SkipTake (OFFSETLIMITSQL) 。 给定页面大小为 10 个结果,可以使用 EF Core 提取第三页,如下所示:

var position = 20;
var nextPage = context.Posts
 .OrderBy(b => b.PostId)
 .Skip(position)
 .Take(10)
 .ToList();

遗憾的是,虽然这种技术非常直观,但它也有一些严重的缺点:

  1. 数据库仍必须处理前 20 个条目,即使它们未返回到应用程序:这会创建可能显著计算负载,该负载会随着跳过的行数而增加。
  2. 如果同时发生任何更新,则分页最终可能会跳过某些条目或显示两次。 例如,如果用户从第 2 页移动到第 3 页时删除了条目,则整个结果集“向上移动”,将跳过一个条目。
Keyset 分页

建议使用基于偏移的分页(有时称为 键集分 页或 基于查找的分页 )的替代方法只是使用 WHERE 子句跳过行,而不是偏移量。 这意味着请记住从提取 (的最后一个条目中获取的相关值,而不是其偏移量) ,并要求在该行之后的下一行。 例如,假设我们提取的最后一个页面的最后一个条目的 ID 值为 55,我们只需执行以下操作:

var lastId = 55;
var nextPage = context.Posts
 .OrderBy(b => b.PostId)
 .Where(b => b.PostId > lastId)
 .Take(10)
 .ToList();

假设定义了索引 PostId,则此查询非常高效,并且对 ID 值较低时发生的任何并发更改也不敏感。

Keyset 分页适用于用户向前和向后导航但不支持随机访问的分页接口,用户可以跳转到任何特定页面。 随机访问分页需要使用偏移量分页,如上所述:由于偏移分页的缺点,请仔细考虑是否确实需要随机访问分页,或者下一页导航是否足够。 如果需要随机访问分页,可靠的实现可以在导航到下一页/上一页时使用键集分页,并在跳转到任何其他页面时偏移导航。

多个分页键

使用键集分页时,经常需要通过多个属性进行排序。 例如,以下查询按日期和 ID 分页:

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();

这可确保下一页准确选取上一页结束的位置。 添加更多的排序键时,可以添加其他子句。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值