与えられた答えのセットへのいくつかの追加:
まず第一に、Redisハッシュを効率的に使用する場合、キーカウントの最大数と値の最大サイズを知っておく必要があります。それ以外の場合は、hash-max-ziplist-valueまたはhash-max-ziplist-entriesが発生した場合、Redisは実際に変換します。内部での通常のキーと値のペア。(hash-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の回答について。
3番目のオプションは実際には本当に楽しいです。max(id)<has-max-ziplist-valueのデータセットの場合、このソリューションはO(N)の複雑さを持っています。これは、Reddisが長さ/キー/値の配列のようなコンテナーとして小さなハッシュを格納するためですオブジェクト!
しかし、多くの場合、ハッシュにはいくつかのフィールドしか含まれていません。ハッシュが小さい場合は、代わりに、長さのプレフィックスが付いたキーと値のペアを持つ線形配列のように、O(N)データ構造にエンコードするだけです。Nが小さい場合にのみこれを行うため、HGETコマンドとHSETコマンドの償却時間はO(1)のままです。ハッシュは、含まれる要素の数が増えすぎるとすぐに実際のハッシュテーブルに変換されます。
しかし、心配する必要はありません。hash-max-ziplist-entriesを非常に速く壊し、実際にはソリューション番号1になります。
2番目のオプションは、フードとして4番目のソリューションに進む可能性が高いです。
ハッシュを使用する場合、値の長さは予測できないことに注意してください。上記のバイオの例のように、すべてが短いわけではありません。
そして、すでに述べたように、4番目のソリューションは、確かに各属性ごとに最も高価な+70バイトです。
そのようなデータセットを最適化する方法についての私の提案:
次の2つのオプションがあります。
一部のユーザー属性の最大サイズを最初の解決策よりも保証できない場合、およびメモリの問題が重要な場合は、redisに格納する前にユーザーjsonを圧縮します。
すべての属性の最大サイズを強制できる場合。hash-max-ziplist-entries / valueを設定して、ユーザー表現ごとに1つのハッシュとして、またはRedisガイドのこのトピックのハッシュメモリ最適化としてハッシュを使用できます:https : //redis.io/topics/memory-optimization andユーザーをjson文字列として保存します。どちらの方法でも、長いユーザー属性を圧縮できます。