我知道我可以使用普通集作为参数(Redis: How to intersect a "normal" set with a sorted set?)来创建一个zinterstore。这会影响性能吗?是否比仅使用zsets更快/更慢?
答案 0 :(得分:1)
默认情况下,Redis假定法线设置为每个元素具有一些默认分数,因此它将法线集视为具有所有元素具有相等默认分数的有序集。我认为性能应该与交叉2个有序集相同。
答案 1 :(得分: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);
存储集和Zset的方式也存在差异,这将影响它们的读取方式。 Redis将决定如何编码(排序)集合,具体取决于它们包含的元素数量。因此,迭代它们需要不同的工作。
然而,出于任何实际目的,我会说你最好的选择是使用ZINTERSTORE
,我会解释原因:我几乎看不到你在源代码中写的任何东西会击败Redis的性能做你想做的交叉。
如果您关心的是表现,那么您的细节就会越来越多。您的重点应该是操作的大O,而是显示在命令documentation中:
时间复杂度:O(N K)+ O(M log(M))最坏情况,N为 最小输入排序集,K是输入排序集的数量和 M是结果排序集中的元素数。
这告诉你的是: 1 - 较小集合的大小和计划交叉的集合数量决定了第一部分。因此,如果你知道你总是相交2套,一套是小的,另一套是巨大的;那么你可以说第一部分是不变的。一个很好的例子就是将商店中所有可用产品的一组(分数是库存中的多少)与用户购物车中的一组有序产品相交。
在这种情况下,你只有2套,你会知道其中一套非常小。
2 - 生成的排序集M的大小可能会导致严重的性能问题。但是这里有一个技巧:当它们太大时,大的有序集被编码为跳过列表。一个小的有序集将被存储为一个zip列表,这可能会导致大型有序集中的重要命中。
但是,对于交叉的情况,您知道结果集不能大于您提供的较小集。对于联合,结果集将包含所有集合中的所有元素;所以需要注意的是更大的集合的规模而不是最小的集合。
总之,使用(已排序)集的性能问题的答案是:它取决于集的大小远远超过实际数据类型。考虑到生成的数据结构将是一个有序集合,而不管所有输入是否已设置。因此,一个大的有序集将被存储(效率较低)作为跳过列表。
事先知道你计划交叉多少套(2,3,取决于用户输入?)和较小集的大小(10?数百?数?)将比内部数据类型更好。交叉算法对于两种类型都是相同的。