【问题标题】:How to paginate more than 10M of records efficiently如何有效地对超过 10M 的记录进行分页
【发布时间】:2020-10-01 17:57:43
【问题描述】:

我需要对托管在 MySQL 上的超过 3000 万用户进行分页。我每页显示 15 个用户,但速度很慢。我的目标是访问任何随机页面并在几毫秒内加载它。

一开始,我使用 MySQL 的 offset 方法,但正如我所说,它很慢(而且肯定是个坏主意)。然后我搬到了 ElasticSearch,但你仍然有一些窗口限制,所以你是有限的。在那之后,我一直在检查不同的方法,比如“光标”方法,但我无法访问任何随机页面。例如,我们从第一页开始,我们有 100000 个页面,我想访问第 4782 个页面,并在几毫秒内加载它。使用 cursor 方法,我只能访问下一个 && prev 页面,而“scroll”方法并不适合我真正需要的。

我的用户 ID 不是按 ID 排序的,所以我不能用它作为分隔符。已经想到Late row lookups

我不介意将所有数据移至新数据库(但会寻找不同的解决方案)。亚马逊在这方面做得很好 (https://www.amazon.com/review/top-reviewers)

使用偏移量查询:

SELECT users.* from users
WHERE users.country = 'DE'
ORDER BY users.posts_count DESC, users.id DESC
LIMIT 15 OFFSET 473

PD:我的用户列表几乎是实时的,所以它每小时都在变化。

有什么想法吗?非常感谢!

【问题讨论】:

  • 我只是对您的用例感到好奇。为什么有人需要访问第 2667 页上的第 40K 用户,就像随机的那样?
  • 例如,如果我是您想在该列表中找到您的用户,并且在知道您的位置几乎在末尾之后,您将需要手写该页面。

标签: mysql performance pagination cursor offset


【解决方案1】:

“访问第 4782 页”——这个用例是什么? “分页”对几页有用,可能是几十页,但不是几千页。

[Next]、[Prev]、[First]、[Last] 很有用。但是如果你想要一个随机探测,那就叫它[随机]探测,而不是“4782页”。

OFFSET 效率低下。以下是对替代方案的讨论:http://mysql.rjweb.org/doc.php/pagination

同时添加INDEX(country, posts_count, id)

【讨论】:

  • 这与它的用例无关,因为正如我们在该链接中看到的那样,亚马逊做得非常快,而且还有很多大公司(Zalando、Aliexpress..等)。现在的问题是如何有效地解决它。当您只有一两个参数要排序时,您的讨论链接非常有用。
【解决方案2】:

使用 Elasticsearch 实现此目的的一种方法是为您的每条记录添加一个线性增加的字段(例如 sort_field)(如果它是线性增加的,则使用您的 ID 字段)。第一条记录的字段值为 1,第二条为 2,第三条为 3,依此类推...

然后,如果您以升序模式按该字段排序,则可以使用search_after feature 直接访问任何记录。

例如,如果你需要访问第4782页(即记录71730及以下),你可以这样实现:

POST my-index/_search 
{
  "size": 15,                      <--- the page size
  "sort": [
    {
      "sort_field": "asc"          <--- properly ordering the records
    }
  ],
  "search_after": [ 71730 ]        <--- direct access to the desired record/page
}

在某些情况下,还可以利用index sorting 功能使排序更快。

注意: 深度分页并不是 Elasticsearch 为之构建的。上面的解决方案有效,但可能有一些缺点(请参阅 cmets),具体取决于您的上下文。它可能不是您需要做的最好的可用技术。

【讨论】:

  • 所以最后,您要添加一个新列,只是为了设置“排名”。但正如我所说,该排名几乎是实时变化的,我认为每次更新该排名都会非常昂贵。 (如果我错了,请纠正我)
  • 那么 Elasticsearch 不是您正在寻找的技术。它本质上是一个搜索引擎,而不是数据库,deep pagination 不是它的优先事项之一
  • 是的,我就是这么想的。这就是为什么我需要一些想法
  • 好的,不过你可以去掉elasticsearch标签,然后
猜你喜欢
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2012-05-09
  • 2015-02-12
  • 2014-04-05
  • 2011-08-24
相关资源
最近更新 更多