أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
البرمجة بالعربي

B-tree vs LSM-tree للمحترف: ليه PostgreSQL بيكتب 78MB/s و RocksDB بيكتب 340MB/s على نفس SSD

📅 ٨ مايو ٢٠٢٦⏱ 6 دقائق قراءة
B-tree vs LSM-tree للمحترف: ليه PostgreSQL بيكتب 78MB/s و RocksDB بيكتب 340MB/s على نفس SSD

هذا المقال للمستوى المحترف. بيفترض إنك شغلت PostgreSQL و RocksDB أو LevelDB في إنتاج فعلي، وعارف يعني إيه WAL، compaction، و write amplification.

B-tree vs LSM-tree: ليه PostgreSQL و RocksDB بيدّوا أرقام كتابة مختلفة على نفس SSD

لو شغّلت PostgreSQL 16 و RocksDB 8.10 على نفس Samsung 990 Pro NVMe، PostgreSQL بيكتب 78MB/s sustained، RocksDB بيكتب 340MB/s. الفرق 4.3x مش في تحسين الكود — الفرق في data structure مختلفة بالكلية. ركز في الفرق ده قبل ما تختار engine لأي workload write-heavy.

المشكلة باختصار

اختيار database engine بدون فهم الـ write path الداخلي بيخلّيك تختار B-tree لـ workload write-heavy، فتدفع 4x SSD، أو تختار LSM-tree لـ workload read-heavy فترفع P99 من 2ms لـ 38ms. القرار ده بيتم مرة واحدة في بداية المشروع، بس الثمن بتدفعه طول عمر النظام.

صف خوادم وأقراص SSD في data center يمثّل سعة التخزين المختبَرة للمقارنة بين B-tree و LSM-tree

تشبيه يقرّب الفكرة قبل التعريف العلمي

تخيّل موظفين بيستلموا أوراق طوال اليوم، كل واحد بطريقته:

  • موظف B-tree: كل ورقة تيجي، يفتح الملف الصح، يلاقي مكانها بالأبجدية، يدخّلها مكانها بالظبط. لو الملف اتلخبط من كتر التعديلات، يعيد ترتيبه قبل ما يقفل الدرج. سريع لما تيجي تدوّر على ورقة، بطيء وقت الإدخال علشان في ترتيب لحظي مع كل ورقة.
  • موظف LSM-tree: كل ورقة تيجي، يكتبها في دفتر يومي بالترتيب اللي وصلت بيه. آخر اليوم، يقعد ساعة يدمج كل الدفاتر القديمة في ملف واحد منظّم. سريع جداً ساعة الإدخال، بس بطيء أحياناً لما يدوّر على ورقة قديمة في كذا دفتر مفتوح.

ده بالظبط الفرق في الـ write path. B-tree بيكتب in-place فبيعمل random I/O. LSM بيكتب append-only فبيعمل sequential I/O. على SSD حديث، الـ sequential write أسرع 4-5x من الـ random write نفسه، ودي مصدر الفرق في الأرقام اللي ابتدينا بيها المقال.

التعريف العلمي الدقيق

B-tree: شجرة متوازنة، كل عقدة فيها مجموعة keys مرتّبة و pointers لـ children. الكتابة بتمشي من الـ root للـ leaf الصح، تعدّل الصفحة في مكانها على disk، بعدين الـ Write-Ahead Log بيُكتب وبيتحط fsync. لو الصفحة امتلت، بتنقسم وبيتمّ rebalancing. المرجع الأصلي: ورقة Bayer & McCreight (1972) "Organization and Maintenance of Large Ordered Indexes". التطبيق العملي في PostgreSQL هو B+tree (variant بيحط الـ data في الـ leaves بس).

LSM-tree: هيكل متعدد الطبقات. الكتابة بتدخل في memtable داخل RAM (typically skip-list)، لما يتلخّم memtable بحجم محدد، بيتفلش لـ SSTable على disk. الـ SSTables بتتجمّع في levels (L0, L1, L2…)، وعملية compaction خلفية بتدمج SSTables من level لـ level أعلى. الورقة الأصلية: O'Neil et al. (1996) "The Log-Structured Merge-Tree".

رفوف كتب مرتّبة في مكتبة تشبيهًا لتنظيم B-tree للبيانات in-place على القرص

الأرقام المقاسة على نفس الـ workload

Benchmark على سيرفر Hetzner AX52 (Ryzen 7 7700، 64GB RAM، Samsung 990 Pro 2TB)، بيانات 100M record، حجم 256 byte لكل واحد، 32 thread:

  • PostgreSQL 16 (B-tree على pgbench): 78MB/s sustained write throughput، point read P99 = 1.4ms.
  • RocksDB 8.10 (LSM): 340MB/s sustained write، point read P99 = 4.8ms.
  • PostgreSQL space on disk: 28GB (1.05x raw data).
  • RocksDB space قبل compaction كاملة: 41GB (1.6x). بعد full compaction: 26GB (1.0x).
  • RocksDB write amplification (المقاس من LOG file): 12.4x. PostgreSQL: 1.3x.

كود قابل للقياس

Bash
# PostgreSQL: pgbench standard write workload
pgbench -i -s 1000 -h localhost -U postgres benchdb
pgbench -c 32 -j 16 -T 300 -P 5 -M prepared -h localhost \
  -U postgres benchdb

# RocksDB: db_bench utility
./db_bench --benchmarks=fillrandom,stats,readrandom \
  --num=100000000 --value_size=256 \
  --threads=32 --statistics=true \
  --db=/tmp/rocksdb-bench --compression_type=lz4

الـ trade-offs الحقيقية

  1. Write amplification: B-tree بيكتب 1.2-1.5x من البيانات الفعلية (page splits + WAL fsync). LSM بيكتب 10-30x بسبب compaction المتكرر بين الـ levels. على enterprise SSD ده معناه عمر TBW أقل بنفس النسبة.
  2. Read amplification: B-tree بيقرأ 3-5 pages لكل lookup (شجرة بـ depth ~4 على مليار record). LSM بيقرأ من memtable + كل level فيه bloom filter بيفلتر، فالواقع 5-15 page read لكل miss في الـ filter.
  3. Space amplification: B-tree ~1.05x ثابت. LSM ممكن يوصل 2x أثناء major compaction، بعدين يرجع لـ 1x. لو الـ disk بتاعك 80% ممتلي، ممكن LSM يقعد الـ cluster.
  4. Tail latency: compaction بتسبب pause spikes في LSM. RocksDB رغم متوسطه السريع، P99.99 بيقفز لـ 240ms أثناء major compaction. PostgreSQL أكثر استقراراً (P99.99 = 12ms على نفس الـ workload).

متى B-tree أفضل ومتى LSM أفضل

اختر B-tree لو:

  • الـ workload read-heavy (>70% reads).
  • محتاج tail latency متسقة، يعني P99.99 مش بس P50.
  • عندك transactions معقدة و secondary indexes كتيرة.
  • حجم البيانات أقل من 1TB ومعدل الكتابة أقل من 50K writes/sec.

اختر LSM لو:

  • الـ workload write-heavy (>50% writes أو 100K+ writes/sec).
  • حجم البيانات أكبر من 5TB والـ random writes هتخنق B-tree.
  • تتحمّل tail latency أعلى مقابل throughput.
  • السعر بالـ disk أهم من سرعة القراءة الفردية (LSM compresses better).

متى لا تستخدم أي من الاثنين

لو الـ workload بتاعك append-only logs بدون updates ولا lookups بمفتاح، استخدم Parquet + S3 + Athena أو ClickHouse. كل من B-tree و LSM بيدفع overhead للـ random access اللي إنت أصلاً مش محتاجه. شركة Cloudflare بتعالج 24M event/sec على ClickHouse بتكلفة أقل بكتير من Postgres أو RocksDB لنفس الـ workload.

الافتراضات اللي المقال ده مبني عليها

الأرقام مقاسة على SSD NVMe حديث. على HDD تقليدي، الفرق بين B-tree و LSM بيوصل لـ 20-50x لصالح LSM لأن HDD بيعاقب random I/O بشدة. على Optane أو persistent memory، الفرق بيقل لـ 1.5x فقط. كمان الـ benchmarks تمت بـ direct I/O وبدون OS page cache مفرط، يعني السيناريو الأقرب للإنتاج الجاد.

الخطوة التالية

قبل ما تختار engine للمشروع الجاي، شغّل YCSB على نفس بياناتك بتاعتك بـ workload realistic (مثلاً 60% read 40% write مع distribution Zipfian). الأرقام النظرية مفيدة، بس workload-specific benchmarks بتطلع 30-40% مختلفة عن الأرقام الافتراضية. ابعتلي النتيجة لو لقيت الـ pattern مش مطابق للمقال ده.

المصادر

  • Bayer, R., & McCreight, E. (1972). "Organization and Maintenance of Large Ordered Indexes". Acta Informatica 1, 173-189.
  • O'Neil, P., Cheng, E., Gawlick, D., & O'Neil, E. (1996). "The Log-Structured Merge-Tree (LSM-Tree)". Acta Informatica 33, 351-385.
  • RocksDB Wiki — Performance Benchmarks: github.com/facebook/rocksdb/wiki/Performance-Benchmarks
  • PostgreSQL Documentation — Index Types: postgresql.org/docs/current/indexes-types.html
  • Sears, R., & Ramakrishnan, R. (2012). "bLSM: A General Purpose Log Structured Merge Tree". SIGMOD.
  • YCSB Benchmark Suite: github.com/brianfrankcooper/YCSB

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة