مقدمة
آلية العمل الأساسية
- اسم الفهرس. يُستخدم اسم الفهرس لإنشاء ملف الفهرس في كل قسم. كما يُطلب أيضًا كمعلمة عند حذف الفهرس أو تجسيده.
- تعبير الفهرس. يُستخدم تعبير الفهرس لحساب مجموعة القيم المخزنة في الفهرس. ويمكن أن يكون مزيجًا من الأعمدة والعوامل البسيطة و/أو مجموعة فرعية من الدوال التي يحددها نوع الفهرس.
- TYPE. يتحكم نوع الفهرس في الحساب الذي يحدد ما إذا كان من الممكن تخطي قراءة كل كتلة فهرس وتقييمها.
- GRANULARITY. تتكون كل كتلة مفهرسة من GRANULARITY من الحبيبات. على سبيل المثال، إذا كانت درجة تحبيب الفهرس الأساسي للجدول 8192 صفًا، وكانت درجة تحبيب الفهرس 4، فستتكون كل “كتلة” مفهرسة من 32768 صفًا.
skp_idx_{index_name}.idx، ويحتوي على قيم التعبير المرتبةskp_idx_{index_name}.mrk2، ويحتوي على الإزاحات المقابلة داخل ملفات أعمدة البيانات المرتبطة.
primary key، يتم فحص جميع القيم المئة مليون في العمود my_value:
my_value يساوي 125 واختيارها، وكيف جرى
تخطي الصفوف التالية من دون القراءة من disk:
يمكنك الوصول إلى معلومات تفصيلية حول استخدام فهرس التخطي من خلال تمكين trace عند تنفيذ queries. من
clickhouse-client، اضبط send_logs_level:
أنواع فهارس التخطي
minmax
set
text
hasAnyToken وhasAllTokens، كما يُحسّن أيضًا جميع وظائف البحث النصي الشائعة.
اطّلع على توثيق الفهرس النصي لمزيد من التفاصيل هنا.
أنواع Bloom filter
mapKeys أو mapValues.
توجد ثلاثة أنواع من فهارس تخطي البيانات تعتمد على Bloom filters:
- الفهرس الأساسي bloom_filter، ويأخذ معاملًا اختياريًا واحدًا لمعدل “الإيجابيات الكاذبة” المسموح به بين 0 و1 (إذا لم يُحدَّد، تُستخدم القيمة .025).
-
الفهرس المتخصص tokenbf_v1 (مهمل). يأخذ ثلاثة معاملات، وكلها مرتبطة بضبط Bloom filter المستخدم: (1) حجم المرشح بالبايت (المرشحات الأكبر تقل فيها الإيجابيات الكاذبة، لكن على حساب قدر من مساحة التخزين)، و(2) عدد دوال hash المطبقة (ومرة أخرى، تؤدي زيادة دوال hash إلى تقليل الإيجابيات الكاذبة)، و(3) قيمة seed لدوال hash الخاصة بـ Bloom filter. راجع الحاسبة هنا لمزيد من التفاصيل حول كيفية تأثير هذه المعاملات في عمل Bloom filter.
يعمل هذا الفهرس فقط مع أنواع البيانات String وFixedString وMap. ويُقسَّم تعبير الإدخال إلى تسلسلات من المحارف تفصل بينها محارف غير أبجدية رقمية. على سبيل المثال، ستحتوي قيمة العمود
This is a candidate for a "full text" searchعلى الرموزThisisacandidateforfulltextsearch. وهو مخصص للاستخدام في عمليات البحث LIKE وEQUALS وIN وhasToken() وعمليات البحث المشابهة عن الكلمات والقيم الأخرى داخل السلاسل النصية الأطول. على سبيل المثال، قد يكون أحد الاستخدامات الممكنة هو البحث عن عدد صغير من أسماء الأصناف أو أرقام الأسطر في عمود يحتوي على أسطر سجلات تطبيقات حرة التنسيق. -
الفهرس المتخصص ngrambf_v1 (مهمل). يعمل هذا الفهرس بالطريقة نفسها التي يعمل بها فهرس token. ويأخذ معاملًا إضافيًا واحدًا قبل إعدادات Bloom filter، وهو حجم ngrams المطلوب فهرستها. والـ ngram هي سلسلة محارف طولها
nمن أي محارف، لذا فإن السلسلةA short stringمع حجم ngram مقداره 4 ستُفهرس على النحو التالي:
بالنسبة لأعباء عمل البحث النصي الكامل، يُوصى باستخدام الفهرس النصي المخصص (انظر Text index for full-text search) بدلًا من الفهرسين المهملين tokenbf_v1 أو ngrambf_v1. يوفر الفهرس النصي inverted index حقيقيًا مع أداء بحث أفضل، وسلوك أكثر قابلية للتنبؤ، ومرونة وأداء أعلى مقارنةً بفهارس Bloom filter المعتمدة على الرموز.
دوال فهارس التخطي
- عند إدراج البيانات ويُعرَّف الفهرس كتعبير دالي (مع تخزين ناتج التعبير في ملفات الفهرس)، أو
- عند معالجة الاستعلام ويُطبَّق التعبير على قيم الفهرس المخزنة لتحديد ما إذا كان ينبغي استبعاد كتلة.
إعدادات فهارس التخطي
- use_skip_indexes (0 أو 1، والقيمة الافتراضية 1). لا يمكن لجميع الاستعلامات استخدام فهارس التخطي بكفاءة. إذا كان من المرجح أن يشمل شرط التصفية معظم الحبيبات، فإن تطبيق فهرس تخطي البيانات يفرض تكلفة غير ضرورية، وقد تكون كبيرة أحيانًا. اضبط القيمة على 0 للاستعلامات التي لا يُتوقع أن تستفيد من أي من فهارس التخطي.
- force_data_skipping_indices (قائمة بأسماء الفهارس مفصولة بفواصل). يمكن استخدام هذا الإعداد لمنع بعض أنواع الاستعلامات غير الفعّالة. في الحالات التي يكون فيها الاستعلام عن جدول مكلفًا جدًا ما لم يُستخدم فهرس تخطٍ، فإن استخدام هذا الإعداد مع اسم فهرس واحد أو أكثر سيؤدي إلى إرجاع استثناء لأي استعلام لا يستخدم أيًا من الفهارس المُدرجة. وهذا من شأنه أن يمنع الاستعلامات المكتوبة بشكل سيئ من استهلاك موارد الخادم.
أفضل ممارسات فهارس التخطي
timestamp، وأن هناك فهرسًا على visitor_id. انظر الاستعلام التالي:
visitor_id المطلوب، سيضم الفهرس الثانوي خمسة مواضع صفوف فقط، ولن تُقرأ من القرص إلا هذه الصفوف الخمسة
فحسب. أما في ClickHouse فالأمر مع فهرس تخطي البيانات معاكس تمامًا. إذ ستُفحص جميع القيم الـ32768 في العمود visitor_id
بغض النظر عن نوع فهرس التخطي.
وبناءً على ذلك، فإن الميل الطبيعي لمحاولة تسريع استعلامات ClickHouse بمجرد إضافة فهرس إلى
أعمدة المفتاح يكون غالبًا في غير محلّه. ولا ينبغي استخدام هذه الإمكانية المتقدمة إلا بعد دراسة بدائل أخرى، مثل تعديل المفتاح الأساسي (راجع How to Pick a Primary Key)، أو استخدام projections، أو استخدام العروض المادية. وحتى عندما يكون فهرس تخطي البيانات مناسبًا، فإن الضبط الدقيق لكلٍ من الفهرس والجدول
يكون ضروريًا في كثير من الأحيان.
في معظم الحالات، يتطلب فهرس التخطي المفيد وجود ارتباط قوي بين المفتاح الأساسي والعمود/التعبير غير الأساسي المستهدف.
فإذا لم يوجد هذا الارتباط (كما في المخطط أعلاه)، فستكون احتمالية أن يستوفي شرط التصفية صف واحد على الأقل من الصفوف الموجودة في
الكتلة التي تضم عدة آلاف من القيم مرتفعة، ولن يُتخطى سوى عدد قليل من الكتل. وعلى النقيض من ذلك، إذا كان نطاق من قيم المفتاح الأساسي (مثل وقت
اليوم) مرتبطًا بقوة بالقيم الموجودة في العمود المرشح للفهرسة (مثل أعمار مشاهدي التلفاز)، فمن المرجح أن يكون الفهرس من نوع minmax
مفيدًا. ولاحظ أنه قد يكون من الممكن زيادة هذا الارتباط عند إدراج البيانات، إما عبر تضمين
أعمدة إضافية في مفتاح الفرز/ORDER BY، أو عبر تجميع عمليات الإدراج بطريقة تجعل القيم المرتبطة بالمفتاح الأساسي مجمّعة عند الإدراج. فعلى
سبيل المثال، يمكن تجميع جميع الأحداث الخاصة بـsite_id معيّن وإدراجها معًا بواسطة عملية الاستيعاب، حتى لو كان المفتاح الأساسي
عبارة عن timestamp يحتوي على أحداث من عدد كبير من المواقع. وسيؤدي ذلك إلى تكوين كثير من الحبيبات التي لا تحتوي إلا على عدد قليل من معرّفات المواقع، بحيث يمكن
تخطي كثير من الكتل عند البحث باستخدام قيمة site_id محددة.
ومن المرشحين الجيدين الآخرين لفهرس التخطي التعبيرات ذات الكاردينالية العالية حيث تكون أي قيمة واحدة متناثرة نسبيًا في البيانات. ومن الأمثلة
على ذلك منصة observability تتعقب رموز الخطأ في طلبات API. فبعض رموز الخطأ، رغم ندرتها في البيانات، قد تكون
مهمة للغاية لعمليات البحث. إذ يتيح فهرس تخطي من نوع set على العمود error_code تجاوز الغالبية العظمى من الكتل التي لا تحتوي على
أخطاء، ومن ثم تحسين الاستعلامات التي تركز على الأخطاء تحسينًا كبيرًا.
وأخيرًا، فإن أفضل ممارسة أساسية هي: اختبر، ثم اختبر، ثم اختبر. ومرة أخرى، وعلى خلاف فهارس b-tree الثانوية أو الفهارس المعكوسة المستخدمة في البحث داخل المستندات،
فإن سلوك فهرس تخطي البيانات ليس سهل التنبؤ. فإضافته إلى جدول تترتب عليها تكلفة ملموسة سواء عند استيعاب البيانات أو عند تنفيذ الاستعلامات
التي لا تستفيد من الفهرس لأي سبب من الأسباب. لذا ينبغي دائمًا اختباره على بيانات من النوع المستخدم في العالم الحقيقي، كما ينبغي أن يشمل الاختبار
اختلافات في النوع، وحجم granularity، وغيرها من المعلمات. وغالبًا ما يكشف الاختبار عن أنماط ومزالق لا تكون واضحة
من خلال التجارب الذهنية وحدها.