주어진 답변에 몇 가지 추가 사항 :
우선 Redis 해시를 효율적으로 사용하려면 키 수 최대 개수와 최대 크기를 알아야합니다. 그렇지 않으면 해시-최대-ziplist 값 또는 해시-최대-ziplist 항목을 분류하면 Redis는이를 실제적으로 변환합니다 후드 아래에서 일반적인 키 / 값 쌍. (해시 -max-ziplist-value, hash-max-ziplist-entries 참조) Redis 내부의 각 일반적인 키 / 값 쌍은 쌍당 +90 바이트를 사용하기 때문에 해시 옵션에서 후드를 깨는 것은 정말 나쁜 일입니다.
옵션 2로 시작하여 실수로 max-hash-ziplist-value를 벗어나면 사용자가 가지고있는 각 속성마다 +90 바이트를 얻게됩니다! (실제로 +90은 아니지만 +70은 아래 콘솔 출력 참조)
# you need me-redis and awesome-print gems to run exact code
redis = Redis.include(MeRedis).configure( hash_max_ziplist_value: 64, hash_max_ziplist_entries: 512 ).new
=> #<Redis client v4.0.1 for redis://127.0.0.1:6379/0>
> redis.flushdb
=> "OK"
> ap redis.info(:memory)
{
"used_memory" => "529512",
**"used_memory_human" => "517.10K"**,
....
}
=> nil
# me_set( 't:i' ... ) same as hset( 't:i/512', i % 512 ... )
# txt is some english fictionary book around 56K length,
# so we just take some random 63-symbols string from it
> redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), 63] ) } }; :done
=> :done
> ap redis.info(:memory)
{
"used_memory" => "1251944",
**"used_memory_human" => "1.19M"**, # ~ 72b per key/value
.....
}
> redis.flushdb
=> "OK"
# setting **only one value** +1 byte per hash of 512 values equal to set them all +1 byte
> redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), i % 512 == 0 ? 65 : 63] ) } }; :done
> ap redis.info(:memory)
{
"used_memory" => "1876064",
"used_memory_human" => "1.79M", # ~ 134 bytes per pair
....
}
redis.pipelined{ 10000.times{ |i| redis.set( "t:#{i}", txt[rand(50000), 65] ) } };
ap redis.info(:memory)
{
"used_memory" => "2262312",
"used_memory_human" => "2.16M", #~155 byte per pair i.e. +90 bytes
....
}
TheHippo 답변의 경우 옵션 1에 대한 의견이 잘못되었습니다.
모든 필드 또는 여러 개의 get / set 작업이 필요한 경우 hgetall / hmset / hmget을 복구합니다.
BMiner의 답변입니다.
세 번째 옵션은 실제로 정말 재미 있습니다 .max (id) <has-max-ziplist-value 값이있는 데이터 세트의 경우이 솔루션에는 O (N) 복잡성이 있습니다. 놀랍게도 Reddis는 작은 해시를 길이 / 키 / 값의 배열과 같은 컨테이너로 저장하기 때문입니다 사물!
그러나 많은 경우 해시는 몇 개의 필드 만 포함합니다. 해시가 작을 때 대신 길이가 미리 지정된 키 값 쌍을 가진 선형 배열처럼 O (N) 데이터 구조로 인코딩 할 수 있습니다. N이 작을 때만이 작업을 수행하므로 HGET 및 HSET 명령의 상각 시간은 여전히 O (1)입니다. 해시가 포함 된 요소 수가 너무 많아지면 실제 해시 테이블로 변환됩니다.
그러나 걱정하지 않아도됩니다. 해시-최대-지퍼리스트 항목을 매우 빠르게 중단하면 실제로 솔루션 번호 1에 도달하게됩니다.
두 번째 옵션은 질문에 따르면 다음과 같은 이유로 네 번째 솔루션으로 갈 것입니다.
해시를 사용하면 값 길이를 예측할 수 없습니다. 위의 바이오 예제와 같이 모두 짧은 것은 아닙니다.
이미 말했듯이 네 번째 솔루션은 각 속성 당 가장 비싼 +70 바이트입니다.
이러한 데이터 세트를 최적화하는 방법에 대한 제안 :
두 가지 옵션이 있습니다.
첫 번째 솔루션보다 일부 사용자 속성의 최대 크기를 보장 할 수없고 메모리 문제가 중요한 경우 redis에 저장하기 전에 사용자 json을 압축하는 것보다 중요합니다.
모든 속성의 최대 크기를 강제 할 수있는 경우 당신은 레디 스 가이드의이 주제에서 해시 메모리 최적화 사용자 표현 당 또는 하나의 해시로 중 해시 최대-ziplist-항목 / 값 및 사용 해시를 설정할 수 있습니다보다 : https://redis.io/topics/memory-optimization 및 사용자를 json 문자열로 저장하십시오. 어느 쪽이든 긴 사용자 속성을 압축 할 수도 있습니다.