เพิ่มเติมบางส่วนของชุดคำตอบที่ให้มา:
ก่อนอื่นถ้าคุณจะใช้ Redis hash อย่างมีประสิทธิภาพคุณต้องรู้ว่ามีปุ่มนับจำนวนสูงสุดและขนาดสูงสุด - มิฉะนั้นถ้ามันแบ่งออก hash-max-ziplist-value หรือ hash-max-ziplist-Redis จะแปลงเป็นจริง คู่ของคีย์ / ค่าปกติภายใต้ประทุน (ดู hash-max-ziplist-value, hash-max-ziplist-entry) และการแตกภายใต้ฮู้ดจากตัวเลือกแฮชคือ BAD จริงๆเพราะแต่ละคู่คีย์ / ค่าปกติภายใน Redis ใช้ +90 ไบต์ต่อคู่
หมายความว่าถ้าคุณเริ่มต้นด้วยตัวเลือกที่สองและตั้งใจแบ่งมูลค่าสูงสุดโดยไม่ตั้งใจคุณจะได้รับ +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 ความคิดเห็นเกี่ยวกับตัวเลือกที่หนึ่งนั้นทำให้เข้าใจผิด:
hgetall / hmset / hmget เพื่อช่วยเหลือหากคุณต้องการฟิลด์ทั้งหมดหรือการดำเนินการ get / set หลายรายการ
สำหรับคำตอบ BMiner
ตัวเลือกที่สามคือความสนุกจริงๆสำหรับชุดข้อมูลที่มี max (id) <has-max-ziplist-value โซลูชันนี้มีความซับซ้อน O (N) เนื่องจากแปลกใจ Reddis เก็บแฮชขนาดเล็กเป็นคอนเทนเนอร์เหมือนอาร์เรย์ที่มีความยาว / คีย์ / ค่า วัตถุ!
แต่แฮชหลายครั้งมีเพียงไม่กี่ฟิลด์ เมื่อแฮชมีขนาดเล็กเราสามารถเข้ารหัสได้ในโครงสร้างข้อมูล O (N) แทนอาเรย์เชิงเส้นที่มีคู่ของคีย์ค่าที่มีคำนำหน้ายาว เนื่องจากเราทำสิ่งนี้เฉพาะเมื่อ N มีขนาดเล็กเวลาที่ค่าตัดจำหน่ายสำหรับคำสั่ง HGET และ HSET ยังคงเป็น O (1): แฮชจะถูกแปลงเป็นตารางแฮชจริงทันทีที่จำนวนองค์ประกอบที่มีจะเติบโตมากเกินไป
แต่คุณไม่ควรกังวลคุณจะแฮ็ก - แม็ก - ซิสทิสต์ - รายการอย่างรวดเร็วและไปที่นั่นตอนนี้คุณอยู่ที่หมายเลข 1
ตัวเลือกที่สองน่าจะเป็นทางออกที่สี่ภายใต้ประทุนเนื่องจากเป็นคำถามที่ระบุไว้:
โปรดทราบว่าหากฉันใช้แฮชความยาวค่าจะไม่สามารถคาดเดาได้ มันไม่ได้สั้นทั้งหมดเช่นตัวอย่างชีวภาพข้างต้น
และอย่างที่คุณพูดไปแล้ว: วิธีที่สี่คือ +70 ไบต์ที่แพงที่สุดสำหรับแต่ละคุณสมบัติ
คำแนะนำของฉันวิธีเพิ่มประสิทธิภาพชุดข้อมูลดังกล่าว:
คุณมีสองตัวเลือก:
หากคุณไม่สามารถรับประกันขนาดสูงสุดของแอตทริบิวต์ผู้ใช้บางอย่างได้มากกว่าที่จะใช้วิธีแก้ไขปัญหาแรกและหากหน่วยความจำมีความสำคัญกว่าการบีบอัดผู้ใช้ json ก่อนเก็บใน redis
หากคุณสามารถบังคับขนาดสูงสุดของคุณลักษณะทั้งหมด กว่าที่คุณสามารถตั้งค่า hash-max-ziplist-entry / value และใช้ hash เป็นหนึ่ง hash ต่อการแสดงของผู้ใช้หรือเป็นการเพิ่มประสิทธิภาพหน่วยความจำ hash จากหัวข้อของคู่มือ Redis นี้: https://redis.io/topics/memory-optimizationและ เก็บผู้ใช้เป็นสตริง json ด้วยวิธีใดวิธีหนึ่งคุณอาจบีบอัดแอตทริบิวต์ผู้ใช้ที่ยาว