我有一棵大的产品目录树,当前包含约3.6万个类别和约100万种产品(即叶子)。它的结构如下(最大深度为5):
Cat1 |_Cat11 | |_Cat111 | | |_Cat1111 | | | |_Product1 | | | |_... | | |_Cat1112 | | | |_Product1 | | | |_... | | |_Cat1113 | | | |_Product1 | | | |_... | |_Cat112 | |_Cat1121 | | |_Product1 | | |_... | |_Cat1122 | | |_Product1 | | |_... | |_Cat1123 | |_Product1 | |_... |_Cat12 | |_Cat121 | | |_Cat1211 | | |_Cat1212 | | |_Cat1213 | |_Cat122 | |_Cat1221 | |_Cat1222 | |_Cat1223 |_... Cat2 |...
在搜索此目录时(使用SQL Server Freetext搜索),我很快就会得到一堆类别和产品。一些搜索会在很多产品上获得成功。我希望对结果进行汇总,并提供当前扩展的每个类别的总匹配数。像这样(2个不同级别的示例):
**Ex1 (first level)** Cat1(563) | Cat2(332) | Cat8(2) **Ex2 (second level)** Cat1 |_Cat12(102) |_Cat14(201) |_...
到目前为止,我已经尝试将所有父/子关系存储在Redis中(存储为集合)。然后,要获得汇总结果,我只需遍历产品(从搜索结果)到其父级,再到当前扩展的类别(或更确切地说是其直属子级),以查找要显示的类别并计算与其匹配的产品数搜索。如果我的搜索结果中有大约5000种产品,则大约需要20秒。漫长的路。
谁会是实现此目标的更好方法?一种方法是让每个类别上的所有100万个产品已经聚合,但这将需要3600万个密钥,并且可能需要大量RAM。我目前已经使用500Mb。
如果要提高速度,则在将结构或“缓存”存储在Redis中时,应尽可能多地准备。如果将产品存储在中HSET,并在此的“产品数据”成员旁边添加类别计数器(每个类别一个)HSET,则可以HINCRBY用来增加/减少计数器。
HSET
HINCRBY
通常(为您的需求设计Redis缓存):您应该尝试防止检索不需要的任何数据。
我建议使用Lua脚本来存储(/更新/删除)以及检索汇总报告。Lua脚本在Redis服务器上执行。ServiceStack支持它们(SCRIPT LOAD+ EVALSHA或简单地EVAL),您还可以尝试BookSleeve C#客户端模块(我们使用它,并且速度更快。 “更快” :良好的Redis数据设计是第一位的)。BookSleeve C#客户端专注于多线程Redis 管道,这可能是您在处理大型数据集时想要的。ServiceStack也应该可以进行流水线操作。
SCRIPT LOAD
EVALSHA
EVAL
如果类别和产品具有整数ID,您也可以将其与结合使用ZSET,在其中您可以将ID用作得分字段。使用a,ZRANGEBYSCORE您可以直接获取“记录”。只要您的ID使用的是15位以下的数字,并且不使用“分数”的小数部分,该技术就很安全。因此,该ID必须保持在-999999999999999到999999999999999的范围内。注:存在这些限制是因为Redis服务器实际上将分数(浮点数)存储为内部的redis字符串表示形式。
ZSET
ZRANGEBYSCORE
希望这会有所帮助,TW