当两个输入集之一是正常集时,zinterstore 会更快/更慢吗?
Posted
技术标签:
【中文标题】当两个输入集之一是正常集时,zinterstore 会更快/更慢吗?【英文标题】:Is a zinterstore going to be faster/slower when one of the two input sets is a normal set? 【发布时间】:2016-09-13 11:18:23 【问题描述】:我知道我可以使用普通集作为参数 (Redis: How to intersect a "normal" set with a sorted set?) 来做一个 zinterstore。这会影响性能吗?它会比只使用 zset 更快/更慢吗?
【问题讨论】:
【参考方案1】:根据sorted-set source code,ZINTERSTORE
会将集合视为得分为 1 的有序集合,函数名称为 zunionInterGenericCommand。
相交集将花费或多或少的时间,具体取决于此步骤中使用的排序算法,例如:
/* sort sets from the smallest to largest, this will improve our
* algorithm's performance */
qsort(src,setnum,sizeof(zsetopsrc),zuiCompareByCardinality);
Sets 和 Zsets 的存储方式也存在差异,这将影响它们的读取方式。 Redis 将根据包含的元素数量来决定如何对(排序的)Set 进行编码。因此,遍历它们需要不同的工作。
但是,出于任何实际目的,我认为您最好的选择是使用 ZINTERSTORE
,我将解释原因:我几乎看不出您在源代码中编写的任何内容在执行你想做的路口。
如果您关心的是性能,那么您对细节的了解就太多了。您的重点应该放在操作的大 O 上,如命令 documentation 中所示:
时间复杂度:O(NK)+O(Mlog(M)) 最坏情况 N 是 最小输入排序集,K是输入排序集的数量, M 是结果排序集中的元素数。
这告诉你的是: 1-较小集合的大小和您计划相交的集合数量决定了第一部分。因此,如果你知道你总是会相交 2 个集合,一个很小,另一个很大;那么你可以说第一部分是不变的。一个很好的例子是将商店中的一组所有可用产品(其中分数是有多少库存)与用户购物车中的一组排序产品相交。
在这种情况下,您将只有 2 套,而且您会知道其中一套非常小。
2-生成的排序集 M 的大小可能会导致很大的性能问题。但是这里有一个技巧:当大的排序集太大时,它们会被编码为跳过列表。一个小的排序集将存储为一个 zip 列表,这可能会在大排序集中造成重要的命中。
但是,对于交集的情况,您知道结果集不能大于您提供的较小集。对于并集,结果集将包含所有集合中的所有元素;所以需要注意大集合的大小而不是最小集合的大小。
总而言之,对(排序的)集合的性能问题的答案是:它取决于集合的大小,而不是实际数据类型。考虑到生成的数据结构将是一个排序集,而不管所有输入是否被设置。因此,一个大的排序集将被存储为一个跳过列表(效率较低)。
事先了解您计划相交的集合数(2、3,取决于用户输入?)以及较小集合的大小(10?数百?数千?)将比内部数据类型提供更好的想法。两种类型的相交算法相同。
【讨论】:
问题只是询问数据类型是否不同是否会影响性能。但答案集中在大O上。我认为答案有点跑题了。【参考方案2】:默认情况下,Redis 假定法线集对每个元素都有一些默认分数,因此它将法线集视为所有元素具有相同默认分数的排序集。我相信性能应该与相交 2 个排序集相同。
【讨论】:
你有来源吗? 尝试分别用元素 a,b 和元素 a,b 和分数 1,2 制作一个排序集。现在尝试使用 AGGREGATE SUM 的 zinterstore,您会看到默认情况下,redis 为正常集合的所有元素分配了一个默认值 这不是我的问题。当然redis就是这样做的。我想知道 zsets 和 sets 的内存使用是否相似。以及在 zinterstore 中组合它们是否比仅使用 zset 更慢/更快。以上是关于当两个输入集之一是正常集时,zinterstore 会更快/更慢吗?的主要内容,如果未能解决你的问题,请参考以下文章