我需要对MySQL上托管的超过3000万用户进行分页。我每页显示15个用户,但速度很慢。我的目标是访问任何随机页面并在几毫秒内加载它。
开始时,我在MySQL中使用offset方法,但是正如我所说的,它相当慢(肯定是个坏主意)。然后我搬到了ElasticSearch,但是您仍然有一些窗口限制,因此受到限制。在那之后,我一直在检查“ cursor”方法之类的不同方法,但是我无法访问任何随机页面。例如,我们从第一页开始,有100000页,我想访问第4782页,并在几毫秒内加载它。使用cursor方法,我只能访问下一个&&上一页,而“ 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:我的用户列表几乎是实时的,因此每小时都在变化。
有什么想法吗?非常感谢!
答案 0 :(得分:1)
“访问第4782页”-用例是什么? “分页”仅对几页有用,也许几十页,但没有几千页。
[下一页],[上一页],[第一],[最后]很有用。但是,如果您要使用随机探针,则将其称为[Random]探针,而不是“ 4782页”。
OFFSET
效率低下。这是替代方案的讨论:http://mysql.rjweb.org/doc.php/pagination
同时添加INDEX(country, posts_count, id)
答案 1 :(得分:0)
使用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构建的。上面的解决方案有效,但根据您的情况可能会有一些缺点(请参阅评论)。对于您需要做的事情,它可能不是最好的可用技术。