Redis zset为什么用跳表

zset相关命令时间复杂度

命令 时间复杂度 功能
zadd O(log(N)) 添加
zscore O(1) 获取score
zcard O(1) 获取member个数
zincrby O(log(N)) 修改score
zrank、zrevrank O(log(N)) 获取排名
zrange、zrevrange O(log(N)+k) 根据排名范围获取
zrangebyscore、zrevrangebyscore O(log(N)+k) 根据分值范围获取
zcount O(log(N)+k) 分值范围内的成员个数
zrem O(k*log(N)) 删除
zremrangebyrank、zremrangebyscore O(log(N)+k) 范围删除
zunionstore O(N)+O(M log(M)) 并集
zinterstore O(N*K)+O(M*log(M)) 交集

数据结构

  • ziplist
    • 元素数量小于128个(zset-max-ziplist-entries)
    • 所有member的长度都小于64字节(zset-max-ziplist-value)
  • dict + skiplist
    • 不满足ziplist条件的

Redis的作者说:

  1. 占用内存更小,更新节点有可能比B树更节约内存。
  2. ZRANGE或ZREVRANGE操作,将跳表作为链表进行遍历,和平衡树是一样的。
  3. 更易于实现,调试。
  • 平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
  • 从内存占用上来说,skiplist比平衡树更灵活一些。一般来说,平衡树每个节点包含2个指针(分别指向左右子树),而skiplist每个节点包含的指针数目平均为1/(1-p),具体取决于参数p的大小。如果像Redis里的实现一样,取p=1/4,那么平均每个节点包含1.33个指针,比平衡树更有优势。

既然跳表也能解决快速查找和更新,为什么MySQL不用跳表,而用了B+树???

发布了151 篇原创文章 · 获赞 72 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/liyuxing6639801/article/details/105252293