تجمع هذه الصفحة أمثلة لفهارس تخطي البيانات في ClickHouse، وتوضح كيفية تعريف كل نوع، ومتى يُستخدم، وكيفية التحقق من تطبيقه. تعمل جميع الميزات مع جداول عائلة MergeTree.
صياغة الفهرس:
INDEX name expr TYPE type(...) [GRANULARITY N]يدعم ClickHouse ستة أنواع من فهارس التخطي:
| نوع الفهرس | الوصف |
|---|---|
| minmax | يتتبع القيم الدنيا والعليا في كل حبيبة |
| set(N) | يخزّن ما يصل إلى N من القيم المميّزة لكل حبيبة |
| text | فهرس مقلوب على البيانات النصية المُجزأة إلى رموز من أجل البحث النصي الكامل |
| bloom_filter([false_positive_rate]) | مرشّح احتمالي للتحقق من الوجود |
| ngrambf_v1 | مرشّح bloom لـ n-gram لعمليات البحث عن سلاسل فرعية |
| tokenbf_v1 | مرشّح bloom قائم على الرموز لعمليات البحث النصي الكامل |
يتضمن كل قسم أمثلة باستخدام بيانات نموذجية، ويوضح كيفية التحقق من استخدام الفهرس أثناء تنفيذ الاستعلام.
فهرس MinMax
يُعد فهرس minmax الأنسب لشروط النطاق على البيانات ذات الترتيب غير المحكم أو على الأعمدة المرتبطة بـ ORDER BY.
-- Define in CREATE TABLE
CREATE TABLE events
(
ts DateTime,
user_id UInt64,
value UInt32,
INDEX ts_minmax ts TYPE minmax GRANULARITY 1
)
ENGINE=MergeTree
ORDER BY ts;
-- Or add later and materialize
ALTER TABLE events ADD INDEX ts_minmax ts TYPE minmax GRANULARITY 1;
ALTER TABLE events MATERIALIZE INDEX ts_minmax;
-- Query that benefits from the index
SELECT count() FROM events WHERE ts >= now() - 3600;
-- Verify usage
EXPLAIN indexes = 1
SELECT count() FROM events WHERE ts >= now() - 3600;اطّلع على مثال عملي يتضمن EXPLAIN واستبعاد البيانات غير اللازمة.
فهرس Set
استخدم فهرس set عندما يكون عدد القيم المميّزة محليًا (في كل كتلة) منخفضًا؛ ولا يكون مفيدًا إذا كانت كل كتلة تحتوي على عدد كبير من القيم المميّزة.
ALTER TABLE events ADD INDEX user_set user_id TYPE set(100) GRANULARITY 1;
ALTER TABLE events MATERIALIZE INDEX user_set;
SELECT * FROM events WHERE user_id IN (101, 202);
EXPLAIN indexes = 1
SELECT * FROM events WHERE user_id IN (101, 202);يوضح دليل التشغيل الأساسي سير عمل الإنشاء/التجسيد والأثر قبل ذلك وبعده.
الفهرس النصي (text) للبحث النصي الكامل
text هو فهرس معكوس للبيانات النصية المُجزأة إلى رموز.
وقد صُمم خصيصًا لأعباء عمل البحث النصي الكامل، مما يتيح بحثًا فعّالًا وحتميًا عن الرموز والمصطلحات.
ويُوصى به لحالات استخدام اللغة الطبيعية أو البحث النصي على نطاق واسع.
راجع البحث النصي الكامل باستخدام الفهارس النصية لمزيد من التفاصيل والأمثلة.
ALTER TABLE logs ADD INDEX msg_text msg TYPE text(tokenizer = splitByNonAlpha);
ALTER TABLE logs MATERIALIZE INDEX msg_text;
SELECT count() FROM logs WHERE hasAllTokens(msg, 'exception');اطّلع على مثال أكثر اكتمالًا عن observability هنا في الوثائق.
الفهرس النصي حتمي بالكامل وقابل للضبط بالكامل من حيث تقسيم النص إلى رموز ومعالجة النص، وذلك مقابل زيادة طفيفة في استهلاك التخزين مقارنةً بالفهارس المعتمدة على bloom filter،
مرشح Bloom عام (قيَمي)
يُعد فهرس bloom_filter مناسبًا لعمليات المساواة والتحقق من العضوية باستخدام IN في حالات "البحث عن إبرة في كومة قش". ويقبل معلمة اختيارية تمثل معدل النتائج الإيجابية الكاذبة (الافتراضي 0.025).
ALTER TABLE events ADD INDEX value_bf value TYPE bloom_filter(0.01) GRANULARITY 3;
ALTER TABLE events MATERIALIZE INDEX value_bf;
SELECT * FROM events WHERE value IN (7, 42, 99);
EXPLAIN indexes = 1
SELECT * FROM events WHERE value IN (7, 42, 99);مرشح Bloom لـ N-gram (ngrambf_v1) للبحث عن السلاسل الفرعية (مهمل)
يقسّم الفهرس ngrambf_v1 السلاسل النصية إلى n-grams. ويعمل بكفاءة مع الاستعلامات LIKE '%...%'. كما يدعم String/FixedString/Map (عبر mapKeys/mapValues)، بالإضافة إلى إمكانية ضبط الحجم وعدد دوال hash والبذرة. راجع وثائق مرشح Bloom لـ N-gram لمزيد من التفاصيل.
-- Create index for substring search
ALTER TABLE logs ADD INDEX msg_ngram msg TYPE ngrambf_v1(3, 10000, 3, 7) GRANULARITY 1;
ALTER TABLE logs MATERIALIZE INDEX msg_ngram;
-- Substring search
SELECT count() FROM logs WHERE msg LIKE '%timeout%';
EXPLAIN indexes = 1
SELECT count() FROM logs WHERE msg LIKE '%timeout%';يوضح هذا الدليل أمثلة عملية ويوضح متى يُستخدم token بدلًا من ngram.
أدوات مساعدة لتحسين المعلمات:
تؤثر معلمات ngrambf_v1 الأربع (حجم n-gram، وحجم bitmap، ودوال hash، وseed) تأثيرًا كبيرًا في الأداء واستهلاك الذاكرة. استخدم هذه الدوال لحساب الحجم الأمثل لـ bitmap وعدد دوال hash استنادًا إلى حجم n-gram المتوقع ومعدل الإيجابيات الكاذبة المطلوب:
CREATE FUNCTION bfEstimateFunctions AS
(total_grams, bits) -> round((bits / total_grams) * log(2));
CREATE FUNCTION bfEstimateBmSize AS
(total_grams, p_false) -> ceil((total_grams * log(p_false)) / log(1 / pow(2, log(2))));
-- Example sizing for 4300 ngrams, p_false = 0.0001
SELECT bfEstimateBmSize(4300, 0.0001) / 8 AS size_bytes; -- ~10304
SELECT bfEstimateFunctions(4300, bfEstimateBmSize(4300, 0.0001)) AS k; -- ~13راجع وثائق المعلمات للاطلاع على إرشادات الضبط الكاملة.
مرشح Bloom للرموز (tokenbf_v1) للبحث المستند إلى الكلمات (مهمل)
يفهرس tokenbf_v1 الرموز المفصولة بمحارف غير حرفية رقمية. ينبغي استخدامه مع hasToken، أو أنماط الكلمات في LIKE، أو equals/IN. وهو يدعم الأنواع String/FixedString/Map.
راجع صفحتي مرشح Bloom للرموز وأنواع مرشح Bloom لمزيد من التفاصيل.
ALTER TABLE logs ADD INDEX msg_token lower(msg) TYPE tokenbf_v1(10000, 7, 7) GRANULARITY 1;
ALTER TABLE logs MATERIALIZE INDEX msg_token;
-- Word search (case-insensitive via lower)
SELECT count() FROM logs WHERE hasToken(lower(msg), 'exception');
EXPLAIN indexes = 1
SELECT count() FROM logs WHERE hasToken(lower(msg), 'exception');اطّلع على أمثلة حول observability وإرشادات بشأن token مقابل ngram هنا.
أضِف الفهارس أثناء CREATE TABLE (أمثلة متعددة)
تدعم فهارس التخطي أيضًا التعبيرات المركبة وأنواع Map/Tuple/Nested. ويوضح المثال أدناه ذلك:
CREATE TABLE t
(
u64 UInt64,
s String,
m Map(String, String),
INDEX idx_bf u64 TYPE bloom_filter(0.01) GRANULARITY 3,
INDEX idx_minmax u64 TYPE minmax GRANULARITY 1,
INDEX idx_set u64 * length(s) TYPE set(1000) GRANULARITY 4,
INDEX idx_ngram s TYPE ngrambf_v1(3, 10000, 3, 7) GRANULARITY 1,
INDEX idx_token mapKeys(m) TYPE tokenbf_v1(10000, 7, 7) GRANULARITY 1
)
ENGINE = MergeTree
ORDER BY u64;تطبيق MATERIALIZE على البيانات الموجودة والتحقق
يمكنك إضافة فهرس إلى أجزاء البيانات الموجودة باستخدام MATERIALIZE، وفحص الاستبعاد باستخدام EXPLAIN أو سجلات التتبّع، كما هو موضح أدناه:
ALTER TABLE t MATERIALIZE INDEX idx_bf;
EXPLAIN indexes = 1
SELECT count() FROM t WHERE u64 IN (123, 456);
-- Optional: detailed pruning info
SET send_logs_level = 'trace';يوضح هذا المثال التطبيقي لـ minmax بنية مخرجات EXPLAIN وعدد عمليات الاستبعاد.
متى تستخدم فهارس التخطي ومتى تتجنبها
استخدم فهارس التخطي عندما:
- تكون قيم التصفية متفرقة داخل كتل البيانات
- يوجد ارتباط قوي بأعمدة
ORDER BY، أو تؤدي أنماط إدخال البيانات إلى تجميع القيم المتشابهة معًا - إجراء عمليات بحث نصي في مجموعات بيانات سجلات كبيرة (النوعان
ngrambf_v1/tokenbf_v1)
تجنب فهارس التخطي عندما:
- يُرجَّح أن تحتوي معظم الكتل على قيمة مطابقة واحدة على الأقل (وسيتم قراءة الكتل في جميع الأحوال)
- التصفية على أعمدة ذات كاردينالية عالية من دون أي ارتباط بترتيب البيانات
تجاهل الفهارس أو فرض استخدامها مؤقتًا
عطّل فهارس معيّنة حسب الاسم لكل استعلام على حدة أثناء الاختبار واستكشاف الأخطاء وإصلاحها. تتوفر أيضًا إعدادات لفرض استخدام الفهارس عند الحاجة. راجع ignore_data_skipping_indices.
-- Ignore an index by name
SELECT * FROM logs
WHERE hasToken(lower(msg), 'exception')
SETTINGS ignore_data_skipping_indices = 'msg_token';ملاحظات ومحاذير
- لا تُدعَم فهارس التخطي إلا في جداول عائلة MergeTree؛ ويتم الاستبعاد على مستوى الحبيبات/الكتل.
- الفهارس المعتمدة على مرشحات Bloom احتمالية (فالنتائج الإيجابية الكاذبة تؤدي إلى قراءات إضافية، لكنها لا تتسبب في تخطي بيانات صالحة).
- ينبغي التحقق من مرشحات Bloom وفهارس التخطي الأخرى باستخدام
EXPLAINوالتتبّع؛ واضبط درجة التحبيب لتحقيق توازن بين الاستبعاد وحجم الفهرس.