Skip to main content
استخدم البيانات المستمدة من سجلات الاستعلامات، والمقارنات المنضبطة، وخطط الاستعلامات لتقييم أساليب التحسين التي تعالج عنق الزجاجة المحدد.

قبل أن تبدأ

ابدأ بخط أساس قابل للتكرار وافتراضٍ بشأن موضع عنق الزجاجة. إذا لم تحدده بعد، فابدأ بـتشخيص الاستعلامات البطيئة وعزل اختناقات الاستعلامات. تستخدم الأمثلة الواردة في هذا الدليل جدول nyc_taxi.trips_small_inferred. ولتشغيلها كما هي، أنشئ الجدول وحمّله إذا لم تكن قد فعلت ذلك مسبقًا:
يبلغ حجم ملف Parquet المصدر نحو 5.8 GB. قد يستغرق تحميله عدة دقائق، حسب الشبكة والموارد المتاحة.

اختر نهجًا

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

تقليل كمية البيانات المقروءة

  • استخدمه عندما: يقرأ الاستعلام أعمدة عريضة أو أعمدة لا يحتاج إليها.
  • التغيير: قلّل حجم الأعمدة التي يقرأها الاستعلام أو عددها.
  • التحقق: قارن بين read_bytes واستخدام الذاكرة والمدة في ظل الظروف نفسها.
لا يقرأ ClickHouse إلا الأعمدة التي يتطلبها الاستعلام، لكنه يظل بحاجة إلى قراءة البيانات المحددة وفك ضغطها ومعالجتها. راجع الأعمدة المحددة وأنواعها. يوفر استنتاج المخطط نقطة انطلاق عملية، لكن الأنواع المستنتجة قد تكون أوسع أو أكثر تساهلًا مما تتطلبه بيانات بيئة الإنتاج.

مراجعة أنواع الأعمدة

اختر أنواعًا دقيقة اختر أنواعًا تحافظ على النطاق والدقة اللذين يتطلبهما حمل العمل، من دون تخزين بيانات أكثر من اللازم. استخدم الأنواع الرقمية وأنواع التاريخ بدلًا من String ذي الاستخدام العام لهذه القيم، واختر أصغر نوع رقمي موقّع أو غير موقّع يمكنه تمثيل النطاق المتوقع بأمان. بالنسبة إلى الأعمدة الزمنية، استخدم Date أو DateTime ما لم تكن بحاجة إلى النطاق الأوسع أو الدقة الكسرية التي يوفرها Date32 أو DateTime64. استخدم الأعمدة القابلة لـ NULL عن قصد يخزّن العمود Nullable قناع NULL منفصلًا إلى جانب قيمه، ويجب على ClickHouse قراءته ومعالجته أيضًا. استخدمه عندما يكون الفرق بين قيمة NULL والقيمة الافتراضية للنوع مهمًا. إذا كان العمود مضمونًا أن يحتوي على قيمة، فتجنّب الأنواع القابلة لـ NULL هذا العمل الإضافي. قبل تغيير عمود، تحقّق من البيانات المصدر ومسار الاستيعاب بدلًا من افتراض أن البيانات غير NULL المرصودة ستبقى كذلك دائمًا. يوضّح مثال التحسين العملي كيفية تحديد الأعمدة التي تحتوي على قيم NULL وقياس أثر تغيير المخطط. استخدم ترميز القاموس للقيم المتكررة يستخدم LowCardinality ترميز القاموس، وغالبًا ما يكون فعالًا لأعمدة String، مثل قيم الحالة ورموز البلدان والأبعاد الأخرى التي يكون عدد قيمها المميزة أقل بكثير من عدد الصفوف. يُعد نحو 10,000 قيمة مميزة نقطة بداية مفيدة لتحديد المرشحين، وليس حدًا ثابتًا. تجنّب المعرّفات والأعمدة الأخرى الفريدة في الغالب، وقارن القياسات قبل تغيير النوع وبعده. راجع اختيار أنواع البيانات للحصول على إرشادات أكثر تفصيلًا.

اقرأ الأعمدة المطلوبة فقط

نظرًا إلى أن ClickHouse يخزّن البيانات حسب الأعمدة، فإن اختيار عدد أقل من الأعمدة يقلّل مباشرةً حجم البيانات المقروءة. حدّد الأعمدة المطلوبة بدلًا من استخدام SELECT *، خصوصًا مع الجداول العريضة أو الاستعلامات التي لا تُرجع سوى مجموعة فرعية صغيرة من كل صف. استخدم read_bytes من system.query_log لمقارنة حجم البيانات المقروءة قبل تقليص الأعمدة المحددة وبعده. إذا ظلّ read_bytes مرتفعًا، فافحص خطة الاستعلام بحثًا عن تعبيرات أو عوامل تصفية أو عمليات ربط أو استعلامات متداخلة لا تزال تتطلب أعمدة إضافية. على سبيل المثال، إذا كانت لوحة المعلومات تحتاج فقط إلى وقت الالتقاط ونوع الدفع والمبلغ الإجمالي، فحدّد هذه الأعمدة بدلًا من الصف كاملًا:
قارن هذا الاستعلام بالاستعلام نفسه باستخدام عامل التصفية والحد نفسيهما مع SELECT *. لن يتغير عدد الصفوف المُعادة، لكن يجب أن تعكس read_bytes قراءة مجموعة أصغر من الأعمدة.

واءم تخطيط البيانات مع الاستعلام

  • يُستخدم عندما: يستمر عامل تصفية انتقائي في قراءة عدد كبير من الأجزاء أو الحبيبات.
  • التغيير: واءم التخطيط الفعلي للبيانات مع عوامل التصفية المستخدمة في الاستعلامات المتكررة.
  • التحقق: قارن الأجزاء والحبيبات التي يحددها EXPLAIN indexes = 1، ثم تحقّق من read_rows وread_bytes والمدة.

ابدأ بمفتاح الترتيب

بالنسبة إلى جداول عائلة MergeTree، يحدد مفتاح الترتيب كيفية تنظيم الصفوف على القرص. افتراضيًا، يعمل أيضًا كمفتاح أساسي يحدد الفهرس الأساسي المتناثر. بخلاف المفتاح الأساسي في قاعدة بيانات OLTP، لا يفرض المفتاح الأساسي في ClickHouse تفرد القيم. وتنبع فائدته على مستوى الأداء من تمكين ClickHouse من تخطي الحبيبات التي لا يمكن أن تستوفي عوامل تصفية الاستعلام. أعطِ الأولوية للأعمدة التي تظهر كثيرًا في عوامل التصفية الانتقائية، مع مراعاة ترتيبها في المفتاح. ويمكن أن يؤدي تجميع القيم ذات الصلة أيضًا إلى تحسين الضغط. وعندما يتوافق ترتيب التجميع أو الفرز في الاستعلام مع المفتاح، قد يستخدم ClickHouse تحسينات التنفيذ بالترتيب لـ GROUP BY أو ORDER BY. قارن الأجزاء والحبيبات التي يختارها EXPLAIN indexes = 1 قبل اختبار مفتاح ترتيب مختلف وبعده. وقارن أيضًا بين read_rows وread_bytes والمدة في الظروف نفسها. راجع اختيار مفتاح أساسي للحصول على إرشادات تفصيلية حول الاختيار. يستخدم جدول المثال ORDER BY ()، لذا لا يوجد مفتاح ترتيب يمكنه استبعاد الحبيبات لفلتر التاريخ الانتقائي التالي:
في ClickHouse 25.9 والإصدارات الأحدث، تضمن هذه الإعدادات أن يعرض EXPLAIN الفهارس المستخدمة والأجزاء والحبيبات التي تستبعدها هذه الفهارس.
استخدم هذا الإخراج كخط أساس. ولإتمام المقارنة، اتبع تطبيق تغيير مفتاح الترتيب في المثال العملي لإنشاء جدول بمفتاح ترتيب يتضمن pickup_datetime، ثم شغّل عليه EXPLAIN نفسه. ينبغي أن يُظهر قسم المفتاح الأساسي في الخطة عددًا أقل من الحبيبات المحددة، قبل استخدام قياسات المدة أو الذاكرة لتقييم التغيير الكلي.
يمكن لـ PREWHERE تقليل قيم الأعمدة المقروءة دون تغيير عدد الصفوف المعالَجة. ينقل ClickHouse تلقائيًا الشروط المؤهلة من WHERE إلى PREWHERE عند تمكين optimize_move_to_prewhere، وهو الإعداد الافتراضي. افحص الخطة قبل إضافة PREWHERE يدويًا، واستخدم read_bytes إلى جانب read_rows عند قياس تأثيره.

قيّم خيارات الفهرسة وتخطيط البيانات الإضافية

إذا تعذّر على مفتاح الترتيب دعم نمط وصول مهم بكفاءة، فقيّم الخيارات الأكثر تخصصًا التالية. استخدم التقسيم لإدارة البيانات واستبعادها يُستخدم التقسيم أساسًا كآلية لإدارة البيانات في عمليات مثل الاحتفاظ والنقل والحذف. ويمكنه تقليل العمل الذي يتطلبه الاستعلام عندما تتيح عوامل التصفية لـ ClickHouse استبعاد أقسام كاملة، لكنه لا ينبغي أن يكون الآلية الأولى لتسريع الاستعلامات. على سبيل المثال، يمكن للأقسام الشهرية دعم حذف أشهر كاملة عندما تُدار مدة الاحتفاظ حسب الشهر أيضًا. لا تلجأ إلى التقسيم إلا إذا كان مفتاح القسم يتوافق مع متطلبات دورة حياة البيانات أو نمط وصول مفهوم جيدًا. حافظ على كارديناليته منخفضة: فالمفتاح عالي الكاردينالية ينشئ أجزاءً كثيرة لا يمكن دمجها عبر الأقسام، وقد يضعف الأداء. استخدم EXPLAIN indexes = 1 للتأكد من أن الاستعلام يستبعد الأقسام فعليًا. أضف فهرسًا لتخطي البيانات لمرشح محلي يخزن فهرس تخطي البيانات بيانات وصفية تتيح لـ ClickHouse تجنب قراءة الكتل التي لا يمكن أن تطابق عامل التصفية. ويكون أكثر فائدة عندما لا يدعم مفتاح الترتيب عامل تصفية مهمًا، وتكون القيم المطابقة متمركزة بدرجة كافية داخل الكتل. على سبيل المثال، يمكن لفهرس bloom filter أن يساعد في عمليات البحث بالمساواة عندما لا تحتوي معظم الكتل على القيمة المطلوبة. استخدم فهارس التخطي بعد مراجعة أنواع البيانات ومفتاح الترتيب. فالفهرس الذي نادرًا ما يستبعد كتلة يضيف عبئًا على التخزين والتقييم دون أن يقلل قدرًا كبيرًا من العمل. اختبر نوع الفهرس ودرجة التفصيل باستخدام بيانات ممثلة، ثم استخدم EXPLAIN indexes = 1 لمقارنة الحبيبات المحددة والتحقق من read_rows وread_bytes والمدة. استخدم الإسقاطات بشكل انتقائي تخزن الإسقاطات تخطيطات بديلة للبيانات إلى جانب الجدول. ويمكنها توفير مفتاح ترتيب آخر أو نتيجة محسوبة مسبقًا، ويمكن لـ ClickHouse اختيار إسقاط مناسب دون الحاجة إلى الإشارة إليه مباشرةً في الاستعلام. على سبيل المثال، يمكن لإسقاط مرتب حسب payment_type دعم عامل تصفية متكرر لا يدعمه ترتيب الجدول الأساسي. استخدم عددًا محدودًا من الإسقاطات لأنماط الوصول المهمة التي لا يستطيع الترتيب الأساسي خدمتها بكفاءة. تخزن الإسقاطات بيانات فهرسة أو بيانات أعمدة إضافية، وتضيف عملًا أثناء الإدراج والدمج؛ كما يكرر الإسقاط كامل الأعمدة الأعمدة التي يخزنها. وقد يؤدي الاستخدام المكثف للإسقاطات أيضًا إلى زيادة العمل اللازم لاختيار الإسقاط الأمثل في وقت الاستعلام. بالنسبة إلى عمليات النشر الكبيرة ذات أنماط الوصول المتنوعة، غالبًا ما تكون الإسقاطات الأقل أو الجداول المنفصلة المصممة لغرض محدد أسهل تشغيلًا. راجع العروض المادية مقابل الإسقاطات عند الاختيار بين هذه الآليات. أضف ترتيبًا بديلًا للاستعلامات التي تُرشّح حسب نوع الدفع ووقت الالتقاط، مع الاستمرار في الاستعلام عن الجدول المصدر:
تعبئة الإسقاط تُنشئ بياناته للبيانات الحالية، بينما تحافظ عليه عمليات الإدراج اللاحقة تلقائيًا. كرر استعلامًا تمثيليًا على الجدول الأصلي، واستخدم EXPLAIN projections = 1 للتحقق مما إذا كان ClickHouse يختار الإسقاط ويقرأ عددًا أقل من الصفوف أو البايتات. قِس أيضًا عبء الإدراج والتخزين قبل تطبيق هذا النمط على نطاق واسع.

احسب الأعمال المتكررة مسبقًا

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

عرض مادي تزايدي

استخدم عرضًا ماديًا تزايديًا عندما يلزم إبقاء عامل تصفية أو تحويل أو تجميع متكرر محدّثًا عند وصول البيانات. يعالج هذا العرض كل كتلة مُدرجة حديثًا ويكتب النتيجة المحوّلة في جدول الهدف. والمقابل هو جهد إضافي لاستيعاب البيانات واستخدام جدول هدف صريح. على سبيل المثال، يمكن للوحة معلومات تحسب الرحلات حسب اليوم بشكل متكرر أن تقرأ من جدول تجميعي صغير بدلًا من تجميع البيانات المصدر لكل طلب:
استعلم من الجدول الهدف باستخدام sum(trip_count) مع التجميع حسب pickup_date لدمج الصفوف التي تنتظر دمجًا في الخلفية أثناء تنفيذ الاستعلام. لا يعالج العرض سوى عمليات الإدراج الجديدة، لذا نفّذ تعبئةً لاحقةً لبيانات المصدر الموجودة بشكل منفصل. تحقّق من التغيير بمقارنة المدة والصفوف المقروءة بالتجميع الأصلي، ثم تأكد من أن عبء الإدراج الإضافي مقبول.

العرض المادي القابل للتحديث

استخدم عرضًا ماديًا قابلًا للتحديث عندما يكون قبول نتائج قديمة قليلًا ممكنًا، ويمكن إعادة احتساب النتيجة كاملةً على فترات زمنية مناسبة. ويُعاد تنفيذ استعلامه وفق جدول زمني. وتتمثل المقايضة في حداثة النتائج وتكلفة كل تحديث. على سبيل المثال، يمكن لتقرير إعادة احتساب إجماليات الرحلات حسب نوع الدفع كل ساعة:
يقرأ التقرير الهدف المُحتسب مسبقًا، بينما يُحدِّث ClickHouse النتيجة الكاملة وفقًا للجدول الزمني. تحقّق من التغيير بمقارنة مدة تنفيذ الاستعلام بالتجميع الأصلي، ثم افحص system.view_refreshes للتأكد من أن مدة التحديث وحالته وتواتره تلائم عبء العمل.

جدول مصمم لغرض محدد

استخدم جدولًا مصممًا لغرض محدد عندما يتطلب عبء عمل منفصل مخططًا أو مفتاح ترتيب أو دورة حياة مختلفة اختلافًا جوهريًا. يوفّر هذا تحكمًا مباشرًا في التصميم المادي، وقد يكون أوضح من صيانة عدد كبير من الإسقاطات. والمقابل هو مساحة تخزين إضافية وإدارة خط أنابيب المعالجة. ويمكن أيضًا نقل عمليات الربط أو التحويلات المتكررة إلى خط أنابيب الاستيعاب إذا كانت بيانات المصدر ومتطلبات حداثتها تجعل ذلك عمليًا. راجع استخدام العروض المادية وإزالة تطبيع البيانات للحصول على إرشادات تفصيلية حول التصميم. على سبيل المثال، أنشئ جدولًا أضيق، بمفتاح ترتيب مناسب للوحة معلومات تُصفّي الرحلات حسب نوع الدفع ووقت الالتقاط:
يستثني هذا المثال قيم NULL لمفتاح الترتيب ويزيل Nullable من هذين العمودين المستهدفين. تأكد من أن هذا النهج يلبّي متطلبات بيانات عبء العمل. يجب أن تستعلم لوحة المعلومات عن هذا الجدول صراحةً، ويجب أن يُبقي مسار الاستيعاب بياناته محدّثة. تحقّق من التغيير بمقارنة الصفوف والبايتات المقروءة واستخدام الذاكرة والمدة مع استعلام الجدول المصدر. ضع في الاعتبار التخزين الإضافي وصيانة مسار المعالجة عند اتخاذ القرار.

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

عند تقييم أي تغيير، أعد إجراء القياسات الأصلية في ظروف مماثلة. وتأكد من أن التغيير يقلل العمل المستهدف دون أن ينقل عنق الزجاجة إلى موضع آخر. تابع إلى مثال التحسين العملي للاطلاع على تغييرات المخطط ومفتاح الترتيب، وقياس أثرها مقارنةً بخط أساس أصلي.
آخر تعديل في ٢٨ أغسطس ٢٠٢٦