如何对分布式数据进行排序和分页?

Posted

技术标签:

【中文标题】如何对分布式数据进行排序和分页?【英文标题】:How do you implement sorting and paging on distributed data? 【发布时间】:2011-04-25 01:27:27 【问题描述】:

这是我要解决的问题:

我需要能够显示存储在多个数据库分片中的分页排序数据表。

分页和排序是众所周知的问题,当数据来自单一来源时,我们大多数人都可以通过多种方式解决这些问题。但是,如果您要跨分片拆分数据或使用 DHT 或分布式文档数据库或任何您喜欢的 NoSQL 风格,事情就会变得更加复杂。

这是一个非常小的数据集的简单图片:

碎片 |数据 1 |一个 1 | D 1 | G 2 |乙 2 |电子 2 | H 3 | C 3 | F 3 |我

分页(Page Size = 3):

页面 |数据 1 |一个 1 |乙 1 | C 2 | D 2 |电子 2 | F 3 | G 3 | H 3 |我

如果我们想向用户显示第 2 页,我们会返回:

D 电子 F

如果有问题的表的大小约为 1000 万行或 1 亿行,您不能只是将所有数据拉到 Web/应用程序服务器上对其进行排序并返回正确的页面。而且您显然不能让每个单独的分片对自己的数据片段进行排序和分页,因为分片彼此不知道。

更复杂的是,我需要呈现的数据不能过时太久,因此提前预先计算一组有用的排序并将结果存储以供以后检索是不切实际的。

【问题讨论】:

【参考方案1】:

有几种解决方案,其中一些可能对您不可行,但也许其中一种会坚持下去:

    按此值的输入范围进行分片(例如,分片 1 包含 A-C,分片 2 D-F 等)。或者,使用另一个具有该表的外键的表作为索引,并使用该系统对索引表进行分片。这样您就可以轻松定位和获取指定范围。如果可以的话,这个解决方案在性能方面可能是最好的(它假设分片的数量是静态的并且分片是可靠的)。 通过二分搜索识别页面项目。例如,假设您想要项目 100 到 110。对于每个分片,按字典顺序计算低于“M”的值的数量。如果数字总和大于 100,则减少枢轴点,否则增加它(使用二分查找)。在确定第 100 个项目(页面上的第一个项目)后,从每个分片中取出比该项目大的前 9 (10 - 1) 个项目,获取它们,对整个列表进行排序,从列表中取出前 9 个,前置第一项就是你的页面!这种方法更难实现,并且需要O(log(n)) 查询,因此它比(1)慢,但如果负载不是很重,仍然可能相当快。 将页码与每个值一起存储。这将使您的读取速度极快,但写入速度却非常慢,因此它仅适用于写入很少(或仅根据有序变量追加)的情况。

【讨论】:

1 和 3 对我来说不可行,但 2 很有趣。我今天将尝试这个想法,看看我能想出什么。 我有一个 2 工作的原型,它看起来是一个很好的解决方案。对基数低的字段进行排序会增加一些复杂性,并且由于重复的计数查询,它有点慢,但它使用的系统资源非常少。 很高兴听到!对我来说,这只是一个理论练习,我很高兴它在实施后奏效了。 如何处理用户设置的几个过滤值产生的动态分页?当您事先不知道平均值是多少时,如何应用您在 2 中公开的算法?谢谢! 我想过在每个分片的每个表上使用 Unix 时间戳 INT 列,然后给定一个带有 WHERE 子句的任意 SELECT 查询,我可以在每个分片上运行这个查询,得到总和COUNT() 所有分片并计算平均 Unix 时间戳(一种 map/reduce 算法)。然后我可以像使用“M”一样使用这个平均时间戳作为二分搜索的基准,这可行吗?

以上是关于如何对分布式数据进行排序和分页?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA:使用连接表进行排序和分页

使用 gridview asp.net 进行排序和分页

如何对分库后的数据进行分页查询

GridView 排序和分页

对datatable操作经验-排序和分页

问题:使用 jquery 插件 tablesorter 进行表格排序和分页