الفهارس الافتراضية هي فهارس تخطٍّ افتراضية مقيّدة بنطاق الجلسة، ويمكنك إلحاقها بجدول من عائلة MergeTree من دون بنائها أو تخزينها فعليًا. وهي لا توجد إلا داخل الجلسة الحالية، ويستخدمها EXPLAIN WHATIF لتقدير أثر فهرس تخطٍّ حقيقي في استعلام — وعادةً ما يكون ذلك في نسبة التخطّي (أي نسبة العلامات التي يمكن تخطّيها) وتكلفة تقريبية بالعلامات والبايتات.
استخدم الفهارس الافتراضية لتقييم الفهارس المرشحة قبل تحمّل تكلفة بنائها فعليًا على القرص.
CREATE INDEX افتراضي
CREATE HYPOTHETICAL INDEX [IF NOT EXISTS] name
ON [db.]table_name (expression) TYPE type[(args)] [GRANULARITY value]تتبع الصياغةُ ALTER TABLE ... ADD INDEX، لكن لا يُنشأ أي فهرس ولا يُكتب — بل يُخزَّن وصف الفهرس فقط ضمن الجلسة الحالية.
name— اسم الفهرس؛ ويجب أن يكون فريدًا ضمن(database, table)في هذه الجلسة.expression— العمود أو التعبير المراد فهرسته.TYPE type— minmax، set(N)، bloom_filter(p)، ngrambf_v1(...)، tokenbf_v1(...). textوvector_similarityغير مدعومَين ويُرفضان عندCREATE، لأن التحقق الفعلي فيALTER TABLE ... ADD INDEXيعتمد على إعدادات على مستوى الجدول لا يستطيع مخزن الجلسة وحده محاكاتها.GRANULARITY value— عدد حبيبات البيانات لكل حبيبة فهرس. والقيمة الافتراضية هي 1.
يجب أن يكون الجدول المستهدف جدولًا من عائلة MergeTree ضمن قاعدة بيانات Atomic (أي يجب أن يكون له معرّف UUID). وتُرفض الجداول التي لا تحتوي على معرّف UUID — مثل الجداول الموجودة في قاعدة بيانات Ordinary قديمة، أو جداول MergeTree ذات الصياغة القديمة — لأن مخزن الجلسة يربط الفهارس الافتراضية بمعرّف UUID الخاص بالجدول.
مثال
CREATE HYPOTHETICAL INDEX idx_b ON t (b) TYPE minmax GRANULARITY 1;تقييم فهرس افتراضي باستخدام EXPLAIN WHATIF
إن تعريف فهرس افتراضي بحد ذاته لا يفعل شيئًا — ولمعرفة كيف سيؤثر في الاستعلام، شغّل EXPLAIN WHATIF على عبارة SELECT تمثيلية. يوضّح المُقدِّر مدى قابلية تطبيق كل فهرس مرشّح، وعدد العلامات التي سيقرأها، ونسبة التخطي الناتجة، وكيف أُنتِج هذا التقدير (empirical أو statistical أو applicability_only).
CREATE TABLE t (a UInt64, b UInt64) ENGINE = MergeTree ORDER BY a
SETTINGS index_granularity = 100;
INSERT INTO t SELECT number, number FROM numbers(10000);
CREATE HYPOTHETICAL INDEX idx_b ON t (b) TYPE minmax GRANULARITY 1;
EXPLAIN WHATIF SELECT * FROM t WHERE b = 42;النتيجة:
Baseline (after PK + partition + existing indexes):
table: default.t
parts: 1
marks: 100
est_bytes: 85.52 KiB
With idx_b (minmax, hypothetical):
status: applicable
marks: 1
est_bytes: 875.00 B
skip_ratio: 99.0%
Estimation:
source: empirical
empirical_status: ok
sampled_parts: 1 / 1
sampled_marks: 100 / 100
elapsed_us: 631est_bytes هو تقدير مستند إلى متوسط حجم الصف في الجدول، لذا يختلف الرقم الدقيق بحسب التخزين والضغط.
لتجاوز الفحص التجريبي داخل الذاكرة والاعتماد بدلًا من ذلك على إحصاءات الأعمدة، عرّفها أولًا للأعمدة المعنية (فهي معطّلة افتراضيًا)، ثم انتظر حتى تكتمل عملية التعديل materialize، وبعدها عطّل المسار التجريبي:
ALTER TABLE t ADD STATISTICS b TYPE tdigest;
ALTER TABLE t MATERIALIZE STATISTICS b SETTINGS mutations_sync = 1;
EXPLAIN WHATIF empirical = 0 SELECT * FROM t WHERE b < 10;With idx_b (minmax, hypothetical):
status: applicable
marks: 1
est_bytes: 1.66 KiB
skip_ratio: 99.9%
Estimation:
source: statistical
empirical_status: disabledراجع مرجع EXPLAIN WHATIF للاطلاع على مخطط الإخراج الكامل والإعدادات.
DROP HYPOTHETICAL INDEX
DROP HYPOTHETICAL INDEX [IF EXISTS] name ON [db.]table_nameيزيل فهرسًا افتراضيًا من الجلسة الحالية.
DROP ALL HYPOTHETICAL INDEXES
DROP ALL HYPOTHETICAL INDEXESيمسح جميع الفهارس الافتراضية المعرَّفة في الجلسة الحالية، بغضّ النظر عن الجدول.
النطاق ومدة البقاء
- لا تبقى الفهارس الافتراضية إلا ضمن الجلسة الحالية — فهي غير مرئية للجلسات الأخرى، وتُزال عند انتهاء الجلسة.
- لا يؤدي تعريف أحدها أو إسقاطه إلى إنشاء أي فهرس، ولا يؤثر مطلقًا في الاستعلامات العادية على الجدول. كما أن
EXPLAIN WHATIFالتجريبي يقرأ بالفعل بيانات الجدول لبناء الفهرس المرشّح في الذاكرة، ويُحتسب هذا المسح ضمن حدود القراءة والحصص الخاصة بالجلسة. - افحص الفهارس الافتراضية الخاصة بالجلسة الحالية عبر
system.hypothetical_indexes.
القيود
تُرفَض العناصر المرشحة text وvector_similarity عند تنفيذ CREATE HYPOTHETICAL INDEX، لأن التحقق الفعلي منها يعتمد على إعدادات على مستوى الجدول لا يمكن لمخزن البيانات الخاص بالجلسة فقط محاكاتها.
يعرض EXPLAIN WHATIF القيمة status: not_applicable للاستعلامات التي تتضمن FINAL (إذ يتداخل تقليم فهرس تخطٍّ مع PrimaryKeyExpand)، ويُرجِع الخطأ NOT_IMPLEMENTED عندما يُنفَّذ الاستعلام من projection (إذ لا تتم materialize لفهرس الجدول الأب على projection parts).
تمثل القيمة التجريبية skip_ratio حدًا أعلى: فهي تحسب كل حبيبة متبقية على نحو مستقل، ولا تُنمذج دمج فجوات seek (merge_tree_min_rows_for_seek / merge_tree_min_bytes_for_seek)، ولا تجمع بين عنصر مرشح وفهرس تخطٍّ موجود ضمن شرط فصلي (OR). لذلك قد يقرأ الفهرس materialized الفعلي مقدارًا أكبر قليلًا، أو يُجري pruning في حالات لا يعكسها هذا التقدير.
الصلاحيات المطلوبة
يتطلب CREATE HYPOTHETICAL INDEX صلاحية SELECT على الأعمدة المشار إليها في تعبير الفهرس — وتكفي صلاحية SELECT على مستوى العمود (مثل GRANT SELECT(b)) — لأن EXPLAIN WHATIF في الوضع التجريبي يقرأ تلك الأعمدة.
لا يتطلب DROP HYPOTHETICAL INDEX وDROP ALL HYPOTHETICAL INDEXES أي صلاحية إضافية؛ إذ يقتصران على إزالة الإدخالات من مخزن الجلسة المحلي.