2016-06-30 45 views
5

私は現在Redisテーブルに約50kハッシュを保存していますが、すべて1つに5つのキーと値のペアがあります。一日に一度、ハッシュ値を更新するバッチジョブを実行します。いくつかのキー値をハッシュ内の他のキーの値に設定することもできます。ここでRedis:すべてのハッシュ値を取得する最良の方法

は、キーとセットを反復処理がnew_code値が所与のハッシュのために存在するかどうnew_codeするold_code私のPythonコードです:

pipe = r.pipeline() 

for availability in availabilities: 
    pipe.hget(availability["EventId"], "new_code") 

for availability, old_code in zip(availabilities, pipe.execute()): 
    if old_code: 
     availability["old_code"] = old_code.decode("utf-8") 

for availability in availabilities: 
    if "old_code" in availability: 
     pipe.hset(
      availability["EventId"], "old_code", availability["old_code"]) 
    pipe.hset(availability["EventId"], "new_code", availability["MsgCode"]) 
pipe.execute() 

それは二回達成するために、私は、キーを反復処理する必要があるように私には少し奇妙です同じ結果が、これを行う良い方法がありますか?

私が理解しようとしている別のことは、最高のパフォーマンスですべてのハッシュ値を取得する方法です。ここで私は現在、それを行う方法です。

d = [] 
pipe = r.pipeline() 
keys = r.keys('*') 
for key in keys: 
    pipe.hgetall(key) 
for val, key in zip(pipe.execute(), keys): 
    e = {"event_id": key} 
    e.update(val) 
    if "old_key" not in e: 
     e["old_key"] = None 
    d.append(e) 

だから、基本的に、私はkeys *その後、値を取得するためにすべてのキーを越えHGETALLで反復ありません。これはあまりにも遅く、特に反復です。それを行うより速い方法がありますか?

+0

プログラミング言語を使用せずに、質問の最初の部分、何をする必要があるのか​​をもう少し詳しく説明できますか? – Malinga

+1

http://stackoverflow.com/questions/38065714/is-there-a-command-in-redis-for-hash-data-structure-similar-to-mget/38066688#38066688ここで私の答えを確認してください – Malinga

+0

すべてのハッシュ/ row現在のコードをnew_codeとして取得し、現在のnew_codeをold_codeとして保存します(以前の状態を記録し、すべてのデータプルでold_codeとnew_codeを比較します)。 –

答えて

5

どのようにアンダーサイドダウンの変更について。データの格納方法を変更します。

の代わりに5つの値を持つ50kハッシュ5つのハッシュを50kの値でそれぞれとしてください。

は、例えば、あなたのハッシュは、イベントIDに依存して、あなたはnew_codeするための部材として、イベントIDが含まれますハッシュマップを持っており、それが値として値だ、

今そのハッシュ内new_code、old_codeおよびその他のstuffsを格納します。したがって、new_codeだけでも、50kメンバー値のペアを含むハッシュマップです。

したがって、50kの代わりに5をループすることは、比較的迅速になります。

私は少し実験を行っているし、次の数字

50k hashes * 5 elements 
Memory : ~12.5 MB 
Time to complete loop through of elements : ~1.8 seconds 

5 hashes * 50k elements 
Memory : ~35 MB 
Time to complete loop through of elements : ~0.3 seconds. 

ある私がKEY_iとVALUE_iのような単純な文字列を使用してテストしている(私はインクリメンタです)ので、メモリがあなたのケースで増加する可能性があります。また、私はちょうどデータを歩いて、私はあなたの場合にも時間が変わるので、何も操作を行っていない。

この変更は、5倍のパフォーマンスを押し上げる、と2倍以上のメモリあなたにを与えることができます見ることができるように。

Redisは範囲内のハッシュの圧縮を行います(デフォルトは512)。その範囲(50k)以上を格納するので、私たちはこのスパイクを記憶に入れます。

基本的にはトレードオフであり、アプリケーションに最適なものを選ぶことができます。あなたの第1の質問については

:あなたは、各ハッシュにnew_codeの値を取得している

  1. 、今あなたは、単一のハッシュで すべてを持っている - > 1つだけのコール。
  2. 次に、old_codeとnew_codeを1つずつ更新しています。これで、1回の呼び出しでhmsetを使用して実行できます。

は、この情報がお役に立てば幸いです。

0

このようなコマンドはありません。ハッシュ内でredisハッシュが機能するため、HMGETは1つのハッシュ内で動作し、そのハッシュ内のすべてのフィールドを指定します。 にある複数のハッシュのすべてのフィールドにアクセスする方法はありません。

は、しかし、この両方のは、あなたの問題への解決策回避策はありません

LUAを使用してパイプライン

  • を使用して2つのオプション

    1. があります。どのようにこの確認を行うかを知るにはこの質問の回答:Is there a command in Redis for HASH data structure similar to MGET?

  • 2

    最初の問題では、Luaスクリプトを使用することで確実にパフォーマンスが向上します。これはテストされていないですが、何かのように:あなたの第二の問題については

    update_hash = r.register_script(""" 
        local key = KEYS[1] 
        local new_code = ARGS[1] 
    
        local old_code = redis.call("HGET", key, "new_code") 
        if old_code then 
         redis.call("HMSET", key, "old_code", old_code, "new_code", new_code) 
        else 
         redis.call("HSET", key, "new_code", new_code) 
        end 
    """) 
    
    # You can use transaction=False here if you don't need all the 
    # hashes to be updated together as one atomic unit. 
    pipe = r.pipeline() 
    
    for availability in availabilities: 
        keys = [availability["EventId"]] 
        args = [availability["MsgCode"]] 
    
        update_hash(keys=keys, args=args, client=pipe) 
    
    pipe.execute() 
    

    あなたは再び短いのLuaスクリプトを書くことによってより速くそれを作ることができます。すべてのキーを取得してクライアントに返す代わりに、スクリプトはそれらに関連付けられたキーとデータを取得し、1回の呼び出しでそれを返します。

    (いずれにしても、いつでもkeys()を呼び出すのが遅いことに注意してください)どちらの方法でも、Redisデータセット全体がローカルメモリに引き込まれることになります。

    関連する問題