2016-06-30 9 views
5

मैं वर्तमान में अपने रेडिस टेबल में लगभग 50k हैश स्टोर करता हूं, प्रत्येक में 5 कुंजी/मूल्य जोड़े होते हैं। एक दिन में मैं एक बैच नौकरी चलाता हूं जो हैश मान अपडेट करता है, जिसमें हैश में अन्य कुंजी के मान पर कुछ महत्वपूर्ण मान सेट करना शामिल है।रेडिस: सभी हैश मान प्राप्त करने का सबसे अच्छा तरीका

यहाँ मेरी अजगर कोड है जो कुंजी और सेट के माध्यम से दोहराता है, तो new_code मूल्य एक दे हैश के लिए मौजूद है new_code को old_code है:

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

जाँच/पंक्ति मैं वर्तमान कोड लाता हूं और इसे new_code के रूप में संग्रहीत करता हूं, जबकि मौजूदा new_code को old_code के रूप में सहेजता है (पिछले राज्य को रिकॉर्ड करने के लिए और पुराने डेटाोड की तुलना में पुराने_code और new_code की तुलना करें)। –

उत्तर

5

एक अपसाइड डाउन चेंज के बारे में कैसे। डेटा को स्टोर करने के तरीके को ट्रांसफर करें।

50k हैश प्रत्येक 5 मूल्य के साथ हैश करने के बजाय। 5 हैश प्रत्येक 50k मूल्य के साथ हैश।

उदाहरण के लिए अपने हैश EventID पर निर्भर करता है और आपको लगता है कि हैश अंदर new_code, old_code और अन्य सामान की दुकान

अब, new_code के लिए एक हैश नक्शा जो एक सदस्य के रूप में शामिल होंगे EventID है और यह मूल्य के रूप में मूल्य है। तो अकेले 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 (जहां मैं incrementer है) की तरह साधारण तार इतना स्मृति का परीक्षण किया है आपके मामले में वृद्धि हो सकती है कर रहे हैं। और मैंने अभी भी डेटा के माध्यम से चले गए हैं, मैंने कोई हस्तक्षेप नहीं किया है, इसलिए आपके मामले में भी समय अलग-अलग होगा।

आप देख सकते हैं यह परिवर्तन आपको 5x प्रदर्शन अप को बढ़ावा देने के दे सकते हैं, और 2 बार अधिक स्मृति

रेडिस एक सीमा (512 - डिफ़ॉल्ट) के भीतर हैश के लिए संपीड़न करता है। चूंकि हम उस सीमा से अधिक भंडारित कर रहे हैं (50k) हमारे पास स्मृति में यह स्पाइक है।

असल में यह एक व्यापार बंद है और यह आपके लिए उपयुक्त है कि आपके आवेदन के अनुरूप सर्वोत्तम विकल्प चुनने के लिए आप पर निर्भर है।

अपने 1 प्रश्न के लिए:

  1. आप प्रत्येक हैश में new_code के मूल्यों हो रही है, अब आप एक ही हैश में सब कुछ है -> बस एक ही कॉल।
  2. फिर आप old_code और new_code को एक-एक करके अपडेट कर रहे हैं। अब आप एक कॉल का उपयोग कर एचएमएससेट का उपयोग कर उन्हें कर सकते हैं।

उम्मीद है कि इससे मदद मिलती है।

0

इस तरह कोई आदेश नहीं है, रेडिस हैश हैश के भीतर काम करता है, इसलिए एचएमजीईटी एक हैश के अंदर काम करता है और उस क्षेत्र में सभी फ़ील्ड देता है। पर एकाधिक हैंश में सभी फ़ील्ड तक पहुंचने का कोई तरीका नहीं है।

हालांकि इस के दोनों समाधानों अपने समस्या का समाधान कर रहे हैं, नहीं 2 विकल्प

  1. पाइपलाइन
  2. का उपयोग LUA

का उपयोग कर रहे हैं। यह जानने के लिए कि यह कैसे करें इस प्रश्न में मेरा उत्तर: Is there a command in Redis for HASH data structure similar to MGET?

2

आपकी पहली समस्या के लिए, एक लुआ स्क्रिप्ट का उपयोग कर निश्चित रूप से प्रदर्शन में सुधार होगा। यह अनचाहे है, लेकिन कुछ ऐसा है:

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() 

आपकी दूसरी समस्या के लिए आप इसे एक छोटी लुआ लिपि लिखकर फिर से तेज़ी से बना सकते हैं। सभी चाबियाँ प्राप्त करने और उन्हें क्लाइंट में लौटने के बजाय, आपकी स्क्रिप्ट को उनके साथ जुड़े कुंजी और डेटा मिलेगा और इसे एक कॉल में वापस कर दिया जाएगा।

(नोट, हालांकि, कि बुला keys() स्वाभाविक धीमी है जहाँ भी आप करते हैं। और ध्यान दें कि या तो दृष्टिकोण आप अनिवार्य रूप से स्थानीय स्मृति है, जो या एक समस्या नहीं हो सकता है हो सकता है में अपने पूरे Redis डाटासेट खींच रहे है।)

संबंधित मुद्दे