Redis學習日記-05:SORT命令

前言

在進行數據排序的時候很容易想到使用ZSET(有序集合)。然而有序集合常見的使用場景是大數據排序,如遊戲玩家排行榜等,因此不多獲取鍵中的所有數據。然而在Redis中對數據的排序除了用有序集合外還可使用SORT命令。
SORT命令能夠對列表、集合、有序集合類型的鍵進行排序。緩存

命令&選項

以列表類型爲例:post

127.0.0.1:6379> lrange post 0 -1
1) "2"
2) "1"
3) "3"

SORT(默認根據元素由小到大):

127.0.0.1:6379> sort post
1) "1"
2) "2"
3) "3"

DESC(逆序):

127.0.0.1:6379> sort post desc
1) "3"
2) "2"
3) "1"

在SORT命令後面加上DESC選項便可將元素逆序排序性能

ALPHA(非數字元素排序):

127.0.0.1:6379> lrange strlist 0 -1
1) "d"
2) "B"
3) "C"
4) "b"
5) "A"

加上ALPHA選項(若是不加該選項會報錯:(error) ERR One or more scores can't be converted into double)大數據

127.0.0.1:6379> sort strlist alpha
1) "A"
2) "b"
3) "B"
4) "C"
5) "d"

該選項會按照字典順序排序。code

BY(參考鍵):

示例1排序

127.0.0.1:6379> hget post:1 count
"10"
127.0.0.1:6379> hget post:2 count
"15"
127.0.0.1:6379> hget post:3 count
"5"
127.0.0.1:6379> lrange post 0 -1
1) "2"
2) "1"
3) "3"
127.0.0.1:6379> sort post by post:*->count
1) "3"
2) "1"
3) "2"

==實例2(某個參考鍵不存在的狀況)==:遊戲

127.0.0.1:6379> lrange post 0 -1
1) "4"
2) "2"
3) "1"
4) "3"
127.0.0.1:6379> hget post:4 count
(nil)
127.0.0.1:6379> sort post by post:*->count
1) "4"
2) "3"
3) "1"
4) "2"
  • 該選項能夠指定一個參考鍵(該參考鍵能夠是字符串類型鍵或者散列類型鍵的某個字段)來進行排序,而不按照待排序鍵的元素大小排序。
    如上所示,BY選項後面的參數「post:->count」,表示按照「post:」開頭的散列的count字段排序,過程當中會用待排序鍵的元素替換「」,即先分別取到post:二、post:一、post:3的count字段的值,分別爲1五、十、5,並按該值由小到大排序(5,10,15)->(post:3,post:1,post:2),最後返回對應的待排序中的元素(3,1,2)。
  • 若是參考鍵是一個常量鍵或者不存在的鍵,則SORT的結果和LRANGE的結果相同,沒有執行排序操做。常量鍵指的是不包含「*」,如「post:1->count」。
  • 若是參考鍵值相同,即若是上述post:一、post:二、post:3的count字段值相同,則SORT會按照待排序鍵元素自己來排序。
  • 若是某個元素對應的參考鍵不存在,則默認參考鍵的值爲0。如上示例2,post:4這個散列並不存在,可是post中元素中加入了4,則排序會按照由小到大(0(post:4默認),5,10,15)->(post:4,post:3,post:1,post:2),最後返回對應的待排序中的元素(4,3,1,2)。

LIMIT(返回指定範圍的結果):

127.0.0.1:6379> lrange post 0 -1
1) "4"
2) "2"
3) "1"
4) "3"
127.0.0.1:6379> sort post limit 1 3
1) "2"
2) "3"
3) "4"

LIMIT選項後面能夠跟兩個參數,一個是offset,表明從那個位置開始;另外一個是count,表明取多少個元素。和Mysql的LIMIT語法很像。字符串

GET(指定排序以後的返回數據):

示例1get

127.0.0.1:6379> sort post by post:*->count get post:*->time
1) (nil)
2) "423"
3) "123"
4) "234"

實例2

127.0.0.1:6379> sort post by post:*->count get post:*->time get #
1) (nil)          ---post:*->time表明的值
2) "4"            ---元素自己的值
3) "423"
4) "3"
5) "123"
6) "1"
7) "234"
8) "2"
  • 實例1能夠看到上面SORT命令後面跟了「get post:->time」,意思是該排序不返回待排序鍵元素自己,而是返回指定的以「post:」開頭的散列類型鍵的time字段。
  • 你也可使用「get #」來使其返回待排序鍵元素自己,如上示例2,依次輸出GET選項對應的值。
  • SORT後面BY選項只能有一個,可是GET選項能夠有多個。

STORE(將排序結果存入另外一個鍵中)

針對上面GET命令示例2中的數據,再附加STORE選項:

127.0.0.1:6379> sort post by post:*->count get post:*->time get # store sort:result
(integer) 8
127.0.0.1:6379> type sort:result
list
127.0.0.1:6379> lrange sort:result 0 -1
1) ""
2) "4"
3) "423"
4) "3"
5) "123"
6) "1"
7) "234"
8) "2"

能夠看到STORE選項後面跟了一個參數鍵sort:result,這個鍵能夠是以前不存在的,命令執行後,會將排序返回的結果存放到該鍵中以列表的形式存在。

總結

  SORT是Redis最強大的命令之一,若是使用不當會形成性能瓶頸。SORT的時間複雜度爲O(n+mlog(m)),其中n表示待排序元素的數量,m表示返回的元素數量。當n很大時,Redis在排序前創建一個長度爲n的容器來存儲待排序元素,所以同時進行大數據量的排序無論是在時間仍是空間上消耗不少,從而下降性能。
  所以使用SORT命令時應該注意如下幾點:

  1. 儘量減小待排序鍵中的元素;
  2. 儘量減小排序以後返回的數據,你可使用上面提到的LIMIT選項來控制;
  3. 若是排序返回的結果較多,儘量使用上面提到的STORE將排序結果緩存起來。
相關文章
相關標籤/搜索