2016-06-30 3 views
5

현재 Redis 테이블에 약 50k 해시를 저장하고 있으며 매 5 개의 키/값 쌍이 있습니다. 하루에 한 번 해시 값을 업데이트하는 일괄 작업을 실행합니다. 일부 키 값을 해시의 다른 키 값으로 설정하는 것도 포함됩니다. 여기 Redis : 모든 해시 값을 얻는 가장 좋은 방법

키와 세트를 반복은 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) 

을 그래서 기본적으로 내가 다음 값을 얻기 위해 모든 키에 걸쳐 HGETALLkeys *을 반복 않습니다 여기에 내가 현재 그것을 할 방법이다. 이것은 너무 느립니다. 특히 반복합니다. 그것을 할 수있는 더 빠른 방법이 있습니까?

+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로 저장합니다 (이전 상태를 기록하고 모든 데이터 풀에서 old_code와 new_code를 비교). –

답변

5

언변이 아래로 변경하는 것은 어떻습니까? 데이터를 저장하는 방식을 변경하십시오.

대신 50k 개의 해시가 있습니다. 값은 각각입니다. 각각 50k 값의 해시가 있습니다 ().

예를 들어 당신의 해시 이벤트 ID에 따라 달라집니다 당신은 new_code에 대한 구성원으로 이벤트 ID를 포함하는 해시 맵이 있으며 값으로 값이다,

이제 해시 내부 new_code, old_code 및 기타 거즈를 저장합니다. 따라서 new_code는 50k 멤버 값 쌍을 포함하는 해시 맵입니다.

그래서 50k가 아닌 5를 반복하면 상대적으로 빠릅니다. 나는 약간의 실험을 수행하고 다음 한

내가 귀하의 경우 증가 할 수 있습니다 간단한 (내가 증가 기입니다) KEY_i 및 VALUE_i 같은 문자열 그래서 메모리를 테스트 한

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. 

숫자입니다. 그리고 또한 방금 데이터를 살펴 보았습니다. 아무런 조작도하지 않았기 때문에 시간이 다를 수도 있습니다.

이 변경 높일 당신에게 5 배의 성능을 제공 할 수 있습니다 볼 수 있듯이

2 배 더 많은 메모리.

Redis는 범위 내에서 해시를 압축합니다 (기본값은 512). 우리가 그 범위 (50k) 이상을 저장하기 때문에 우리는이 스파이크를 기억합니다.

기본적으로 이는 상쇄 관계에 있으며 응용 프로그램에 가장 적합한 최상의 것을 선택해야합니다. 당신의 첫번째 질문에 대한

: 각 해시에 new_code의 값을 받고

  1. , 지금은 하나의 해시 모든 것을 가지고 -> 단 하나의 호출.
  2. 그런 다음 old_code 및 new_code를 하나씩 업데이트하고 있습니다. 이제는 단일 호출을 사용하여 hmset을 사용하여 작업을 수행 할 수 있습니다.

희망이 도움이됩니다.

0

해시 내에 redis 해시가 작동하므로 HMGET은 한 해시 내부에서 작업하고 해당 해시의 모든 입력란을 제공합니다. 에서 여러 해시의 모든 입력란에 액세스 할 수있는 방법이 없습니다.

그러나이 모두가 당신의 문제에 대한 해결책 해결하지

LUA을 사용하여 파이프 라인

  • 를 사용하여이 옵션

    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 스크립트를 작성하여 다시 빠르게 만들 수 있습니다. 모든 키를 가져 와서 클라이언트에 반환하는 대신 스크립트는 키와 연관된 데이터를 가져와 한 번의 호출로 반환합니다.

    (어디에서든지 keys()은 본질적으로 속도가 느리며 두 방법 중 하나를 사용하면 전체 Redis 데이터 세트를 로컬 메모리로 가져 오는 것이므로 문제가 될 수도 있고 없을 수도 있음을 유의하십시오.)

    관련 문제