redis sorted sets操作学习笔记
sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加
修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有
两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
和set一样sorted set也是string类型元素的集合,不同的是每个元素都会关联一个double
类型的score。sorted set的实现是skip list和hash table的混合体。
当元素被添加到集合中时,一个元素到score的映射被添加到hash table中,所以给定一个
元素获取score的开销是O(1),另一个score到元素的映射被添加到skip list,并按照score排
序,所以就可以有序的获取集合中的元素。添加,删除操作开销都是O(log(N))和skip list的
开销一致,redis 的skip list实现用的是双向链表,这样就可以逆序从尾部取元素。sorted set最
经常的使用方式应该是作为索引来使用.我们可以把要排序的字段作为score存储,对象的id
当元素存储.
下面讲一个使用 Sorted Sets 的例子
mysql中有一张表,假设名字为 summary_data吧,记录数为30M左右,
有一个字段first_path 为varchar(256),需要找到出现次数最多的10个first_path。
方法一 ) 直接sql语句
sql语句很好写:
代码如下 | |
SELECT first_path, COUNT(*) AS c FROM summary_data GROUP BY first_path ORDER BY c DESC LIMIT 10; |
表上面是有索引的, 但是索引的长度为 KEY `first_path` (`first_path`(255)), 也许是这个原因导致了无法使用索引:
id: 1
select_type: SIMPLE
table: summary_data
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 28136948
Extra: Using temporary; Using filesort
这条sql运行了9分钟。
把first_path都导出来,生成文件 input/first_path, 每行一条记录,话说这个导出的过程真的很慢。
方法二 ) sort 与 uniq
sort input/first_path | uniq -c |sort -nr | head -n 10
排好序的状态,就是分组的状态了。
uniq -c 用来统计每组的数量。
sort -nr 再对统计结果进行降序
一分半钟搞定。
方法三 ) redis的sorted set
用这种方法,只因为突然想到sorted set就是为此而生的嘛。
client libary 准备用 hiredis.
安装很简单: make && make install
可以看到库文件安装到了 /usr/local/lib/ 目录
头文件安装到了 /usr/local/include/hiredis/ 目录
需要把 /usr/local/lib/ 添加到 /etc/ld.so.conf
然后ldconfig
编译一下:
代码如下 | |
gcc -I /usr/local/include/hiredis -lhiredis ./example.c |
16分钟出结果, not good enough。