redis二级指标与性能问题

fnatzsnv  于 2021-06-08  发布在  Redis
关注(0)|答案(2)|浏览(401)

我知道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"

哪种方法是首选方法,尤其是与性能相关的方法?

ohfgkhjo

ohfgkhjo1#

zset对score使用skiplist,对hashset使用dict。如果您添加所有具有相同分数的元素,skiplist将变为类似于b树的结构,对于字典顺序搜索,它的时间复杂度为o(logn)。
所以,如果您不总是对电话号码执行范围查询,您应该使用电话号码的订单列表作为精确查询的键。这也适用于电子邮件(您可以使用哈希来组合这两个列表)。这样,查询的性能将比zset好得多。

zd287kbt

zd287kbt2#

关于:除了在末尾加一个“z”之外,还有更好的方法来获得范围吗?是的,请使用下一个直接字符,而不是添加 Z :

zrangebylex phone-index [7245551212 (7245551213

当然,第二种方法提供了更好的性能。
使用排序集进行词典编制索引时,需要考虑:
元素的添加, ZADD ,是 O(log(N)) 询问, ZRANGEBYLEX ,是 O(log(N)+M) 其中n是排序集中的元素数,m是返回的元素数
相反,使用列表:
另外, RPUSH ,是 O(1) 查询lrange是 O(N) 因为你从零开始。
也可以使用集合( SADD 以及 SMEMBERS )不同的是,列表允许重复和保留顺序,集合确保唯一性,不尊重插入顺序。

相关问题