基于偏移量、游标分页的详解

前言

大量的数据集往往会被分成多个空间去存储。例如一本书就会有几十页几百页,因为把一本书都放在一页去展示不管是对生产者还是消费者都是及其不友好的。又比如在网页中我们常常会看到一页一页的数据,当然我们自己开发的时候也少不了做分页展示的需求。

基于偏移量进行分页

对于分页我们相较于使用游标进行分页更熟悉、见得更多的是基于偏移量进行分页。
例如这样一个Get请求:brownjay.com/api/v1/books?page=2&size=10

这一个请求会提供一个一页的size和页数,那么我们很容易就可以知道offset为(page-1)*size

后端就会执行select *** from *** limite 10 offset 10

这种分页方式十分简单,只需跳过前面Offset指定的结果数,按需返回Limit个结果数就可以了,它很容易与数据库查询语句对应。

你有100本书,每一页展示10本,那么基于偏移量的分页方式如下。

  • 第一页:Offset:0, Limit:10
  • 第二页:Offset:10, Limit:10
  • 第三页:Offset:20, Limit:10

基于游标进行分页

基于游标分页是怎样的,我通过一个sql便知select *** from ***where id >10 limite 10

不同于使用offset进行偏移的分页,游标是通过cursor去直接进行where进行范围的筛查。
其效果都能拿到那一段区域的数据集

简单实现Demo:

我们定义一个代码分页信息的结构体。

type Page struct {
	NextID        string `json:"next_id"`
	NextTimeAtUTC int64  `json:"next_time_at_utc"`
	PageSize      int64  `json:"page_size"`
}

其中:

  • NextID就是cursor
  • NextTimeAtUTC记录分页发生的时间点
  • PageSize表示每一页的元素个数

它有一个Encode方法,生成一个使用Base-64编码的令牌。

// Encode 返回分页token
func (p Page) Encode() Token {
	b, err := json.Marshal(p)
	if err != nil {
		return Token("")
	}
	return Token(base64.StdEncoding.EncodeToString(b))
}

Token代表的是分页令牌,本质上是一个字符串。

type Token string

它有一个Decode方法,用来从字符串令牌中解析得到分页信息。

// Decode 解析分页信息
func (t Token) Decode() Page {
	var result Page
	if len(t) == 0 {
		return result
	}

	bytes, err := base64.StdEncoding.DecodeString(string(t))
	if err != nil {
		return result
	}

	err = json.Unmarshal(bytes, &result)
	if err != nil {
		return result
	}

	return result
}

这样一个简单的基于游标的分页功能就实现好了。

最终客户端会在url中携带相应token,我们就会解析出相应的nextID(cursor),而我们在vo中也会返回下一页所对应的token以便客户端进行访问

值得注意的是我们没有直接在API请求链接中使用真实数据的主键等信息,而是使用JSON序列化并使用Base-64编码的字符串来作为token来使用,这样做能防止用户直接解密我们的系统而避免风险

而为什么要在分页信息中记录时间,是为了防止token泄漏后被无限期使用(爬虫)。我们可以限制token在一个合理时间后失效,也是安全性的一个保障。

优劣势分析

对于偏移量分页

优势:

  • 使用偏移量进行分页实现起来显然是相对更简单,并且这种实现还可以进行跳页进行查询访问

劣势:

  • 1.基于偏移量的分页在数据量很大的场景下,查询效率会比较低。通常 OFFSET 越高,查询时间就越长,而反观where进行筛选则可以使用b+树索引去进行筛选,O(logn)>>O(n)

  • 2.在并发场景下会出现元素重复(offset在第二页时有人在第一页新插入一个数据)或被跳过(offset在第二页时有人在第一页删掉了一个数据)。

  • 3.显式的page参数在支持跳页的同时也会被爬虫并发请求。


对于游标分页

优势:

  1. 1.性能好(where ***可以使用索引)
  2. 2.并发安全
  3. 3.不会被无脑批量爬取

劣势:

  • 1.实现相较于偏移量更复杂
  • 2.不支持跳页
  • 3.不适合多检索条件的场景

最后问问看到封面你会想到哪一句诗呢?😀

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值