Symfoware

Symfowareについての考察blog

Redis ハッシュ登録とjson形式での登録の速度差(redis-py)

Redisにハッシュ形式でデータ登録できますが、ふとjsonエンコードした文字列を
登録するのとどちらが有利かなと思ったので簡単にテスト。



hmsetでの登録



まず、hmsetでの登録。
pipelineを使用して、10000件一括で登録してみます。


  1. # -*- coding:utf-8 -*-
  2. import datetime
  3. import redis
  4. # 登録用のデータを適用に用意(10フィールド)
  5. map_value = {}
  6. for i in xrange(10):
  7.     map_value['value_%d' %i] = u'適当な文字列を設定しておく'
  8. start = datetime.datetime.now()
  9. # redis client準備
  10. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  11. pipe = r.pipeline()
  12. # 1000件登録
  13. for i in xrange(10000):
  14.     pipe.hmset('key:%d' % i, map_value)
  15. # 登録実行
  16. pipe.execute()
  17. stop = datetime.datetime.now()
  18. print(stop - start)





5回実行した結果は以下の通り。


0:00:00.733393
0:00:00.722198
0:00:00.734545
0:00:00.740826
0:00:00.731590







hgetallでデータ取得



すべてのデータを取得してみます。


  1. # -*- coding:utf-8 -*-
  2. import datetime
  3. import redis
  4. start = datetime.datetime.now()
  5. # redis client準備
  6. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  7. # 検索だけ実行
  8. for i in xrange(10000):
  9.     ret = r.hgetall('key:%d' % i)
  10. stop = datetime.datetime.now()
  11. print(stop - start)




実行結果


0:00:04.116560
0:00:04.142717
0:00:04.007236
0:00:04.099062
0:00:04.241744






jsonで登録



次はjsonで。


  1. # -*- coding:utf-8 -*-
  2. import datetime
  3. import json
  4. import redis
  5. # 登録用のデータを適用に用意(10フィールド)
  6. map_value = {}
  7. for i in xrange(10):
  8.     map_value['value_%d' %i] = u'適当な文字列を設定しておく'
  9. json_data = json.dumps(map_value)
  10. start = datetime.datetime.now()
  11. # redis client準備
  12. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  13. pipe = r.pipeline()
  14. # 1000件登録
  15. for i in xrange(10000):
  16.     pipe.set('key:%d' % i, json_data)
  17. # 登録実行
  18. pipe.execute()
  19. stop = datetime.datetime.now()
  20. print(stop - start)




実行結果


0:00:00.260260
0:00:00.272462
0:00:00.235066
0:00:00.415741
0:00:00.239506








jsonデータの取得



jsonの値を取得してエンコードします。


  1. # -*- coding:utf-8 -*-
  2. import datetime
  3. import json
  4. import redis
  5. start = datetime.datetime.now()
  6. # redis client準備
  7. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  8. # 検索だけ実行
  9. for i in xrange(10000):
  10.     ret = json.loads(r.get('key:%d' % i))
  11. stop = datetime.datetime.now()
  12. print(stop - start)





実行結果。


0:00:02.665833
0:00:02.780447
0:00:02.745389
0:00:02.860698
0:00:02.753706








まとめ



だたhashを登録したいだけなら、jsonデコードしたほうが良さそうな結果になりました。

パターンpipeline登録単件検索10,000回
hash0.73254.1214
json0.28462.7612

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/31(木) 23:51:25|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redis hashの値でソートする(luaスクリプト使用)

Redis 2.6以降でluaスクリプトが実行できました。
Redisでluaスクリプトを実行する(redis-py使用)

これを応用して、hashの値でソートしてみます。


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. # redis client準備
  4. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  5. # 適当に値を登録
  6. r.hmset('id:1', {'map_key':'value-1'})
  7. r.hmset('id:2', {'map_key':'value-2'})
  8. # luaスクリプト
  9. lua = """
  10. local value = redis.call('KEYS', KEYS[1])
  11. local t = {}
  12. for i,v in ipairs(value) do
  13.     local map = redis.call('HGETALL', v)
  14.     
  15.     local temp = {}
  16.     temp['key'] = v
  17.     
  18.     local k = ''
  19.     for j,jv in ipairs(map) do
  20.         if j % 2 == 0 then
  21.             temp[k] = jv
  22.         else
  23.             k = jv
  24.         end
  25.         
  26.     end
  27.     
  28.     table.insert(t, temp)
  29. end
  30. table.sort(t, function(a, b) return a.map_key > b.map_key end)
  31. local ret = {}
  32. for i,v in ipairs(t) do
  33.     local row = v.key .. ',' .. 'map_key:' .. v.map_key
  34.     table.insert(ret, row)
  35. end
  36. return ret
  37. """
  38. # luaスクリプトを登録
  39. multiply = r.register_script(lua)
  40. # スクリプト実行
  41. ret = multiply(keys=['id:*'])
  42. # 結果を表示
  43. print ret




うまく行ったみたいです。


$ python sample.py
['id:2,map_key:value-2', 'id:1,map_key:value-1']


テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/31(木) 23:22:12|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redisでluaスクリプトを実行する(redis-py使用)

Redis 2.6以降から、luaスクリプトを実行できるようになったみたいです。
redis-pyを使用して試してみます。


サンプル



luaスクリプトで「redis」という暗黙オブジェクトが使えます。
これでデータの操作が行えます。

Pythonのプログラムから渡した値は、
「KEYS[num]」「ARGV[num]」というキーワードで取り出せる模様。


  1. # -*- coding:utf-8 -*-
  2. import redis
  3. # redis client準備
  4. r = redis.Redis(host='192.168.1.101', port=6379, db=0)
  5. # 適当に値を登録
  6. r.set('test1', 'test_value_1')
  7. r.set('test2', 'test_value_2')
  8. # luaスクリプト
  9. lua = """
  10. local value_1 = redis.call('GET', KEYS[1])
  11. local value_2 = redis.call('GET', KEYS[2])
  12. return ARGV[1] .. ':' .. value_1 .. ':' .. value_2
  13. """
  14. # luaスクリプトを登録
  15. multiply = r.register_script(lua)
  16. # スクリプト実行
  17. ret = multiply(keys=['test1', 'test2'], args=['arg_value'])
  18. # 結果を表示
  19. print ret




実行してみると、こんな結果が表示されました。


$ python sample.py
arg_value:test_value_1:test_value_2



テーマ:データベース - ジャンル:コンピュータ

  1. 2014/07/31(木) 23:08:25|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Redis 2.4系 hashの値でソートする(sortコマンド)

Redisでソートができるのか調べてみました。

参考にしたのはこちら。

https://redis-docs.readthedocs.org/en/latest/SortCommand.html
http://grokbase.com/t/gg/redis-db/1236403prq/sort-with-hash

簡単には行かないので、この方法は微妙な気がします。



sortコマンド



まず、基本となるのはリストをソートする「sort」コマンド。

saddコマンドを使用し、「sort_key」というキー名で「1」「2」「3」という値を登録しました。


> sadd sort_key 1
> sadd sort_key 2
> sadd sort_key 3



sort sort_keyで、登録した値を並び替えます。


> sort sort_key
1) "1"
2) "2"
3) "3"




逆順はdescをつけます。


> sort sort_key desc
1) "3"
2) "2"
3) "1"




まず、これが基本の考え方。





データの登録



hsetコマンドで、ハッシュ形式のデータを登録します。

キーが
「data:[num]」

フィールド名、値が2つ。
「field_a」「field_a_[num]_value」
「field_b」「field_b_[num]_value」


[num]は、sort_keyで登録した値に揃えます。


> hmset data:1 field_a field_a_1_value field_b field_b_1_value
> hmset data:2 field_a field_a_2_value field_b field_b_2_value
> hmset data:3 field_a field_a_3_value field_b field_b_3_value




登録したデータはこんな感じ。


> hgetall data:1
1) "field_a"
2) "field_a_1_value"
3) "field_b"
4) "field_b_1_value"

> hgetall data:2
1) "field_a"
2) "field_a_2_value"
3) "field_b"
4) "field_b_2_value"

> hgetall data:3
1) "field_a"
2) "field_a_3_value"
3) "field_b"
4) "field_b_3_value"






並び替えて結果を取得



こんな感じで、並び替えた値が取得出来ました。


> sort sort_key get data:*->field_a
1) "field_a_1_value"
2) "field_a_2_value"
3) "field_a_3_value"

> sort sort_key get data:*->field_a desc
1) "field_a_3_value"
2) "field_a_2_value"
3) "field_a_1_value"

> sort sort_key get data:*->field_b desc
1) "field_b_3_value"
2) "field_b_2_value"
3) "field_b_1_value"

> sort sort_key get data:*->field_b
1) "field_b_1_value"
2) "field_b_2_value"
3) "field_b_3_value"




どうも、予めキー名にマッチするリストを準備しておかないといけないようです。

テーマ:データベース - ジャンル:コンピュータ

  1. 2014/07/31(木) 22:46:28|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

RedisにPythonで画像データを登録する(redis-py使用)

Redisに画像(バイナリデータ)が登録できるか試してみました。



  1. # -*- coding:utf-8 -*-
  2. import redis
  3. # redis client準備
  4. r = redis.Redis(host='192.168.1.110', port=6379, db=0)
  5. # 適当な画像データを開く
  6. f = open('sample.png', 'rb')
  7. binary = f.read()
  8. f.close()
  9. # redisに登録
  10. r.set('pic', binary)
  11. # 取り出して保存
  12. f = open('result.png', 'wb')
  13. f.write(r.get('pic'))
  14. f.close()




あっさり成功です。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/07/31(木) 22:23:14|
  2. Redis
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ