【发布时间】:2011-12-15 20:55:09
【问题描述】:
假设您有一大组具有A 和B 属性的#m 对象。您可以使用哪种数据结构作为索引(或哪种算法)来提高以下查询的性能?
find all objects where A between X and Y, order by B, return first N results;
即按范围A 过滤并按B 排序,但只返回前几个结果(例如,最多1000 个)。插入非常罕见,因此可以接受繁重的预处理。我不对以下选项感到满意:
-
记录(或索引)按 B 排序:按
B顺序扫描记录/索引,返回第一个N,其中A匹配X-Y。在最坏的情况下(很少有对象与范围 XY 匹配,或者匹配位于记录/索引的末尾),这将变为O(m),这对于大小为m的大型数据集来说还不够好。 记录(或索引)按 A 排序:进行二分查找,直到找到与 X-Y 范围匹配的第一个对象。扫描并创建一个对与范围匹配的所有
k对象的引用数组。按 B 对数组进行排序,返回第一个N。那是O(log m + k + k log k)。如果k很小,那么这确实是O(log m),但如果k很大,那么排序的成本甚至比线性扫描所有mobjects 的成本还要糟糕。自适应 2/1:对 X-Y 范围内的第一个匹配项进行二分搜索(使用 A 上的索引);对范围的最后一个匹配项进行二进制搜索。如果范围很小,继续算法 2;否则恢复到算法 1。这里的问题是我们恢复到算法 1 的情况。虽然我们检查了“很多”对象通过了过滤器,这对于算法 1 来说是很好的情况,但这个“很多”最多是一个常数 (渐近地,
O(n)扫描将始终胜过O(k log k)排序)。所以我们仍然有一个O(n)算法来处理一些查询。
是否有允许在亚线性时间内回答此查询的算法/数据结构?
如果不是,为了达到必要的性能,有什么好的折衷办法?例如,如果我不保证返回对象的B 属性的最佳排名(召回
【问题讨论】:
-
你在使用一些数据库吗?还是在硬文件中序列化?或者它在内存中的对象数组中
-
数据适合内存,所以假设。没有数据库(即在某种意义上,应用程序就是数据库,问题是如何计划/回答这个查询:-)
-
是
A和B整数吗?或者A和B可以翻译成整数吗? -
是的,A 和 B 是/可以是整数。此外,在我想到的更复杂和更具体的问题中,可以将 A 减少到少数可能的范围(例如 0-100、101-200、...)——但实际问题要多得多复杂。
标签: algorithm search data-structures indexing