我知道redis实际上没有二级索引的概念,但是可以使用z*命令来模拟二级索引。我有一个关于处理以下情况的最佳方法的问题。
我们使用redis来跟踪订单。但我们也希望能够通过电话号码或电子邮件id找到这些订单。因此,以下是我们的数据:
> set 123 7245551212:dlw@email.com
> set 456 7245551212:dlw@email.com
> set 789 7245559999:kdw@email.com
> zadd phone-index 0 7245551212:123:dlw@email.com
> zadd phone-index 0 7245551212:456:dlw@email.com
> zadd phone-index 0 7245559999:789:kdw@email.com
我可以通过以下方式查看电话号码的所有订单(除了在末尾添加一个“z”之外,还有更好的方法获取范围吗?):
> zrangebylex phone-index [7245551212 (7245551212Z
1) "7245551212:123:dlw@dcsg.com"
2) "7245551212:456:dlw@dcsg.com"
我的问题是,这会有好的表现吗?或者我们应该仅仅创建一个由电话号码键控的列表,并将订单id添加到该列表中?
> rpush phone:7245551212 123
> rpush phone:7245551212 456
> rpush phone:7245559999 789
> lrange phone:7245551212 0 -1
1) "123"
2) "456"
哪种方法是首选方法,尤其是与性能相关的方法?
2条答案
按热度按时间ohfgkhjo1#
zset对score使用skiplist,对hashset使用dict。如果您添加所有具有相同分数的元素,skiplist将变为类似于b树的结构,对于字典顺序搜索,它的时间复杂度为o(logn)。
所以,如果您不总是对电话号码执行范围查询,您应该使用电话号码的订单列表作为精确查询的键。这也适用于电子邮件(您可以使用哈希来组合这两个列表)。这样,查询的性能将比zset好得多。
zd287kbt2#
关于:除了在末尾加一个“z”之外,还有更好的方法来获得范围吗?是的,请使用下一个直接字符,而不是添加
Z
:当然,第二种方法提供了更好的性能。
使用排序集进行词典编制索引时,需要考虑:
元素的添加,
ZADD
,是O(log(N))
询问,ZRANGEBYLEX
,是O(log(N)+M)
其中n是排序集中的元素数,m是返回的元素数相反,使用列表:
另外,
RPUSH
,是O(1)
查询lrange是O(N)
因为你从零开始。也可以使用集合(
SADD
以及SMEMBERS
)不同的是,列表允许重复和保留顺序,集合确保唯一性,不尊重插入顺序。