我认为这是一个有趣的问题。您正在寻找集群,但您并不真正关心集群是否有序。简短的回答是,不,没有这样的事情。
确实,对集群进行排序确实过度指定了您的要求,但是对于规模不大的问题,这是指定答案的最有效方法。让我们考虑一下 SQL Server 将如何满足您的请求。
让我们假设在第一种情况下,您的数据处于无序堆中,即没有聚集索引,并且您很少这样做。为了满足您的要求,SQL Server 可以立即返回第一行,因为您不关心顺序。但是,在它可以从第二个集群返回任何内容之前,它必须获取整个结果集以了解最后一行是否属于第一个集群。因此,在从磁盘读取所有内容之前,您几乎无法获得很多结果。
到目前为止,第一个场景非常简单,但让我们考虑一下 SQL Server 可能如何跟踪这些集群。假设您有n
属于m
集群的数据行。当 SQL Server 遍历您的结果时,它可以立即返回属于第一个集群的结果。但是,对于其他m-1
集群,它需要将它们存储在某个地方。
SQL Server 将其索引保存在树中,因此让我们首先考虑这一点。对于m-1
集群,树需要O(log(m))
很深。因此,找到任何特定行所属的集群的运行时间是O(log(m))
。该查询的总运行时间为O(n x log(m))
。
SQL Server 可以做得更好吗?它可以通过将这些索引保存在哈希中。在 a has 中找到一行的簇的时间是O(1)
。因此,总运行时间为O(n)
。这里的权衡是散列需要时间,一个好的散列函数很难确定,而且散列需要保留比实际需要更多的空间才能获得良好的性能。因此,对于小问题,树更快、更有效。
所以在第一种情况下,我们能做的最好的事情是O(n)
,一个很小但很重要的常数。
让我们考虑第二种情况,您希望在蓝月亮中多次执行此查询。你会想要一个索引。该索引将所有行保存在集群中,并且所有集群都按O(m)
每次插入的成本排列。你得到什么回报?您的查询只需要从顶部(或底部)遍历索引,返回它看到的每一行。这会给你一个有序的结果。查询中不需要任何工作。我们在插入时完成了所有操作(以及更新和删除)。
所有这些都假设您的表被安排在一个磁盘上,其中访问这些数据的最有效方法是从一端到另一端遍历数据。当您跨磁盘对数据进行分区时,这不再适用。虽然我认为你应该将数据保存在内存中,但你不能总是负担得起那么多内存,所以分区很重要。
对于分区的情况,我强烈推荐一种 RAID 解决方案,这样您的所有查询都会受益,而不仅仅是这个。通过以较小的规模进行条带化,无论您的数据如何分布,您都可以获得性能。除非您碰巧获取仅属于一个磁盘的数据,否则没关系。
如果您在 RAID 无法正常工作的非对称设备上进行分区,那么也许您可以考虑将多个查询拼接在一起,每个查询恰好跨越一个分区。