هل تبحث عن دليل؟
اطّلع على دليلنا لأفضل ممارسات JSON للاطلاع على أمثلة وميزات متقدمة واعتبارات تتعلق باستخدام نوع JSON.
JSON مستندات JavaScript Object Notation (JSON) في عمود واحد.
في ClickHouse مفتوح المصدر، تم تصنيف نوع بيانات JSON على أنه جاهز للإنتاج في الإصدار 25.3. ولا يُنصح باستخدام هذا النوع في بيئة الإنتاج في الإصدارات السابقة.
JSON، يمكنك استخدام البنية التالية:
| المعلمة | الوصف | القيمة الافتراضية |
|---|---|---|
max_dynamic_paths | معلمة اختيارية تشير إلى عدد المسارات التي يمكن تخزينها بشكل منفصل كأعمدة فرعية ضمن كتلة بيانات واحدة تُخزَّن بشكل منفصل (على سبيل المثال ضمن جزء بيانات واحد لجدول MergeTree). إذا تم تجاوز هذا الحد، فسيتم تخزين جميع المسارات الأخرى معًا في بنية واحدة تُسمى البيانات المشتركة. توجد أيضًا طرق لتغيير الحد الأقصى للمسارات الديناميكية دون تغيير هذه المعلمة. | 1024 |
max_dynamic_types | معلمة اختيارية تتراوح بين 1 و 255 تشير إلى عدد أنواع البيانات المختلفة التي يمكن تخزينها بشكل منفصل داخل عمود مسار واحد من النوع Dynamic ضمن كتلة بيانات واحدة تُخزَّن بشكل منفصل (على سبيل المثال ضمن جزء بيانات واحد لجدول MergeTree). إذا تم تجاوز هذا الحد، فسيتم تخزين جميع الأنواع الجديدة معًا في بنية واحدة تُسمى shared variant. | 32 |
some.path TypeName | تلميح نوع اختياري لمسار معيّن في JSON. ستُخزَّن هذه المسارات دائمًا كأعمدة فرعية بالنوع المحدد. | |
SKIP path.to.skip | تلميح اختياري لمسار معيّن يجب تخطيه أثناء تحليل JSON. لن يتم أبدًا تخزين هذه المسارات في عمود JSON. إذا كان المسار المحدد كائن JSON متداخلًا، فسيتم تخطي الكائن المتداخل بالكامل. | |
SKIP REGEXP 'path_regexp' | تلميح اختياري يتضمن تعبيرًا نمطيًا يُستخدم لتخطي المسارات أثناء تحليل JSON. لن يتم أبدًا تخزين أي مسار يطابق هذا التعبير النمطي في عمود JSON. |
متى تستخدم النوع JSON
JSON للاستعلام عن حقول محددة داخل كائنات JSON وتصفيتها وتجميعها عندما تكون بنيتها ديناميكية أو غير متوقعة. ويحقق ذلك عبر تقسيم كائنات JSON إلى أعمدة فرعية منفصلة، ما يقلل بدرجة كبيرة من حجم البيانات المقروءة ويُسرّع الاستعلامات على الحقول المحددة مقارنةً ببدائل مثل Map أو تحليل السلاسل النصية.
لكن هذا ينطوي على بعض المقايضات المهمة:
- بطء عمليات
INSERT- إن تقسيم JSON إلى أعمدة فرعية، وإجراء استنتاج النوع، وإدارة هياكل تخزين مرنة، يجعل عمليات الإدراج أبطأ مقارنةً بتخزين JSON في عمودStringبسيط. - بطء عند قراءة الكائنات كاملةً - إذا كنت بحاجة إلى استرجاع مستندات JSON كاملة (بدلاً من حقول محددة)، فإن النوع
JSONيكون أبطأ من القراءة من عمودString. فالعبء الإضافي الناتج عن إعادة تكوين الكائنات من الأعمدة الفرعية المنفصلة لا يحقق أي فائدة عندما لا تُجري استعلامات على مستوى الحقول. - عبء تخزيني إضافي - إن الاحتفاظ بأعمدة فرعية منفصلة يضيف عبئًا بنيويًا مقارنةً بتخزين JSON كسلسلة نصية واحدة.
استخدم النوع JSON عندما:
- تكون بياناتك ذات بنية ديناميكية أو غير متوقعة، مع مفاتيح تختلف من مستند إلى آخر
- تتغير أنواع الحقول أو البُنى بمرور الوقت أو تختلف بين السجلات
- تحتاج إلى الاستعلام أو التصفية أو التجميع على مسارات محددة داخل كائنات JSON التي لا يمكنك توقّع بنيتها مسبقًا
- تتضمن حالة الاستخدام لديك بيانات شبه مهيكلة مثل السجلات أو الأحداث أو المحتوى الذي ينشئه المستخدم، مع بُنى غير متسقة
استخدم عمود String (أو الأنواع المهيكلة) عندما:
- تكون بنية بياناتك معروفة ومتسقة — في هذه الحالة، استخدم الأعمدة العادية أو الأنواع
TupleوArrayوDynamicوVariantبدلًا من ذلك - تُعامَل مستندات
JSONعلى أنها blobs معتمة لا تُخزَّن ولا تُسترجَع إلا كاملةً، من دون تحليل على مستوى الحقول - لا تحتاج إلى إجراء استعلامات أو تصفية على حقول
JSONالفردية داخل قاعدة البيانات - يكون
JSONمجرد تنسيق للنقل/التخزين، ولا يُحلَّل داخل ClickHouse
إنشاء JSON
JSON.
استخدام JSON ضمن تعريف عمود في جدول
Query (Example 1)
Response (Example 1)
Query (Example 2)
Response (Example 2)
استخدام CAST مع ::JSON
::JSON.
التحويل باستخدام CAST من String إلى JSON
Query
Response
CAST من Tuple إلى JSON
Query
Response
CAST من Map إلى JSON
Query
Response
يتم تخزين مسارات JSON بشكل مسطّح. وهذا يعني أنه عند تنسيق كائن JSON انطلاقًا من مسار مثل سيُرجع:وليس:
a.b.c
لا يمكن معرفة ما إذا كان ينبغي إنشاء الكائن بالشكل { "a.b.c" : ... } أو { "a": { "b": { "c": ... } } }.
ويفترض تنفيذنا دائمًا الاحتمال الثاني.على سبيل المثال:استعلام
الاستجابة
قراءة مسارات JSON كأعمدة فرعية
JSON قراءة كل مسار بوصفه عمودًا فرعيًا منفصلًا.
إذا لم يُحدَّد نوع المسار المطلوب في تعريف النوع JSON،
فسيكون العمود الفرعي لهذا المسار دائمًا من النوع Dynamic.
على سبيل المثال:
Query
Response
Query (Reading JSON paths as sub-columns)
Response (Reading JSON paths as sub-columns)
getSubcolumn لقراءة الأعمدة الفرعية من النوع JSON:
Query
Response
NULL:
Query
Response
Query
Response
a.b، يكون النوع UInt32 كما حددناه في تعريف نوع JSON،
أما في جميع الأعمدة الفرعية الأخرى، فالنوع هو Dynamic.
ومن الممكن أيضًا قراءة الأعمدة الفرعية من النوع Dynamic باستخدام الصياغة الخاصة json.some.path.:TypeName:
Query
Response
Dynamic إلى أي نوع بيانات. في هذه الحالة، سيتم طرح استثناء إذا تعذّر تحويل النوع الداخلي داخل Dynamic إلى النوع المطلوب:
Query
Response
Query
Response
لقراءة الأعمدة الفرعية بكفاءة من أجزاء Compact في MergeTree، تأكّد من تفعيل إعداد MergeTree write_marks_for_substreams_in_compact_parts.
قراءة الكائنات الفرعية في JSON كأعمدة فرعية
JSON قراءة الكائنات المتداخلة كأعمدة فرعية من النوع JSON باستخدام الصياغة الخاصة json.^some.path:
Query
Response
Query
Response
عندما تُخزَّن المسارات في البيانات المشتركة الأساسية (
map)، فقد لا تكون قراءة الأعمدة الفرعية للكائنات الفرعية فعّالة، لأنها تتطلب فحص بنية البيانات المشتركة بالكامل. أما مع map_with_buckets أو تسلسل البيانات المشتركة advanced، فتكون قراءة الأعمدة الفرعية من البيانات المشتركة محسّنة بدرجة كبيرة.قراءة الأعمدة الفرعية المجمّعة في JSON
JSON قراءة مسار باعتباره عمودًا فرعيًا مجمّعًا باستخدام الصياغة الخاصة json.@some.path.
ويُرجع العمود الفرعي المجمّع لمسار معيّن ما يلي:
- القيمة الحرفية المخزّنة في ذلك المسار على أنها
Dynamic، إذا كان المسار يحتوي على قيمة حرفية. - كائن JSON فرعيًا في ذلك المسار على أنه
Dynamic، إذا لم يكن المسار يحتوي على قيمة حرفية ولكن كانت له مسارات فرعية متداخلة. NULL، إذا لم تكن هناك قيمة حرفية أو أي مسارات فرعية لذلك المسار.
json.a) والعمود الفرعي للكائن الفرعي (json.^a).
يقارن المثال التالي بين أنواع الأعمدة الفرعية الثلاثة للمسار a:
Query
Response
Query
Response
- الصف 1: تحتوي
aعلى قيمة حرفية42. يُرجعjson.aهذه القيمة بصيغةDynamic(Int64)، ويُرجعjson.^aكائنًا فرعيًا فارغًا{}(لا توجد مفاتيح متداخلة تحتa)، ويُرجعjson.@aالقيمة الحرفية42. - الصف 2: تحتوي
aعلى كائن متداخل. يُرجعjson.aالقيمةNULL(لا توجد قيمة حرفية في هذا المسار)، ويُرجعjson.^aالكائن الفرعي بصيغةJSON، ويُرجعjson.@aأيضًا الكائن الفرعي بصيغةDynamic(JSON). - الصف 3:
aغير موجودة بالكامل. يُرجع كلٌّ منjson.aوjson.@aالقيمةNULL، بينما يُرجعjson.^aكائنًا فارغًا{}.
عند تخزين المسارات في البيانات المشتركة الأساسية (
map)، قد تكون قراءة الأعمدة الفرعية المجمّعة غير فعّالة لأنها تتطلب فحص بنية البيانات المشتركة بالكامل. ومع map_with_buckets أو تسلسل البيانات المشتركة advanced، تصبح قراءة الأعمدة الفرعية من البيانات المشتركة محسّنة بدرجة كبيرة.استنتاج الأنواع للمسارات
JSON، يحاول ClickHouse تحديد نوع البيانات الأنسب لكل مسار JSON.
ويعمل ذلك بطريقة مشابهة لـ الاستدلال التلقائي على المخطط من بيانات الإدخال،
ويُتحكَّم فيه بالإعدادات نفسها:
- input_format_try_infer_dates
- input_format_try_infer_datetimes
- schema_inference_make_columns_nullable
- input_format_json_try_infer_numbers_from_strings
- input_format_json_infer_incomplete_types_as_strings
- input_format_json_read_numbers_as_strings
- input_format_json_read_bools_as_strings
- input_format_json_read_bools_as_numbers
- input_format_json_read_arrays_as_strings
- input_format_json_infer_array_of_dynamic_from_array_of_different_types
Query
Response
Query
Response
Query
Response
Query
Response
التعامل مع مصفوفات من كائنات JSON
Array(JSON)، وتُدرَج في عمود Dynamic لذلك المسار.
ولقراءة مصفوفة من الكائنات، يمكنك استخراجها من عمود Dynamic كعمود فرعي:
Query
Response
Query
Response
max_dynamic_types/max_dynamic_paths في نوع JSON المتداخل مقارنةً بالقيم الافتراضية.
وهذا ضروري لتجنّب ازدياد عدد الأعمدة الفرعية بشكل غير متحكَّم فيه داخل المصفوفات المتداخلة من كائنات JSON.
لنحاول قراءة الأعمدة الفرعية من عمود JSON متداخل:
Query
Response
Array(JSON) باستخدام صيغة خاصة:
Query
Response
[] بعد المسار إلى مستوى الـ Array. على سبيل المثال، سيُحوَّل json.path[][] إلى json.path.:Array(Array(JSON))
لنلقِ نظرة على المسارات والأنواع داخل Array(JSON):
Query
Response
Array(JSON):
Query
Response
JSON متداخل:
Query
Response
التعامل مع مفاتيح JSON ذات القيمة NULL
null وغياب القيمة أمرين متكافئين:
Query
Response
التعامل مع مفاتيح JSON التي تحتوي على نقاط
a.b والقيمة 42. وأثناء تنسيق JSON، نُكوِّن دائمًا كائنات متداخلة استنادًا إلى أجزاء المسار المفصولة بنقطة:
Query
Response
{"a.b" : 42} مُنسقًا الآن على الشكل {"a" : {"b" : 42}}.
ويؤدي هذا القيد أيضًا إلى تعذّر تحليل كائنات JSON صالحة مثل هذا:
Query
Response
25.8). في هذه الحالة، أثناء التحليل ستُحوَّل جميع النقاط في مفاتيح JSON عبر
الإفلات إلى %2E، ثم يُزال عنها الإفلات مرة أخرى أثناء التنسيق.
Query
Response
Query
Response
Query
Response
json.`a.b` يعادل العمود الفرعي json.a.b ولن يقرأ المسار الذي يحتوي على نقطة مُفلَتة:
Query
Response
SKIP/SKIP REGEX)، فعليك استخدام نقاط مسبوقة بمحرف الإفلات في التلميح:
Query
Response
Query
Response
قراءة نوع JSON من البيانات
JSONEachRow,
TSV,
CSV,
CustomSeparated,
Values، إلخ) قراءة نوع JSON.
أمثلة:
Query
Response
CSV/TSV/إلخ، يُحلَّل JSON من سلسلة نصية تحتوي على كائن JSON:
Query
Response
الوصول إلى الحد الأقصى للمسارات الديناميكية داخل JSON
JSON تخزين سوى عدد محدود من المسارات داخليًا على هيئة أعمدة فرعية منفصلة.
ويبلغ هذا الحد افتراضيًا 1024، لكن يمكنك تغييره في تعريف النوع باستخدام المعلمة max_dynamic_paths.
عند الوصول إلى هذا الحد، ستُخزَّن جميع المسارات الجديدة المُدرجة في عمود JSON في بنية بيانات مشتركة واحدة.
ولا يزال من الممكن قراءة هذه المسارات كأعمدة فرعية،
لكن ذلك قد يكون أقل كفاءة (راجع القسم الخاص بالبيانات المشتركة).
وهذا الحد ضروري لتجنّب وجود عدد هائل من الأعمدة الفرعية المختلفة، مما قد يجعل الجدول غير قابل للاستخدام.
لنرَ ما يحدث عند الوصول إلى هذا الحد في بضعة سيناريوهات مختلفة.
الوصول إلى الحد أثناء تحليل البيانات
JSON في البيانات، وعند الوصول إلى الحد للكتلة الحالية من البيانات،
ستُخزَّن جميع المسارات الجديدة في بنية بيانات مشتركة. يمكننا استخدام دالتي الاستبطان التاليتين JSONDynamicPaths وJSONSharedDataPaths:
Query
Response
e و f.g، تم الوصول إلى الحد،
وأُدرجا في بنية بيانات مشتركة.
أثناء دمج أجزاء البيانات في محركات جداول MergeTree
MergeTree، قد يصل العمود JSON في جزء البيانات الناتج إلى حدّ المسارات الديناميكية،
وبالتالي لن يتمكن من تخزين جميع المسارات من الأجزاء المصدرية كأعمدة فرعية.
في هذه الحالة، يحدد ClickHouse المسارات التي ستبقى كأعمدة فرعية بعد الدمج، والمسارات التي ستُخزَّن في بنية البيانات المشتركة.
في معظم الحالات، يحاول ClickHouse الإبقاء على المسارات التي تحتوي على
أكبر عدد من القيم غير NULL، ونقل المسارات الأقل شيوعًا إلى بنية البيانات المشتركة. ومع ذلك، يعتمد هذا على طريقة التنفيذ.
لنلقِ نظرة على مثال لهذا النوع من الدمج.
لنبدأ أولًا بإنشاء جدول يحتوي على عمود JSON، وضبط حدّ المسارات الديناميكية على 3، ثم إدراج قيم تحتوي على 5 مسارات مختلفة:
Query
JSON على مسار واحد:
Query
Response
Query
Response
a وb وc، ونقل المسارين d وe إلى بنية بيانات مشتركة.
كما ذُكر في القسم السابق، عند بلوغ الحد max_dynamic_paths، تُخزَّن جميع المسارات الجديدة في بنية بيانات مشتركة واحدة.
في هذا القسم، سنستعرض تفاصيل بنية البيانات المشتركة وكيفية قراءة الأعمدة الفرعية للمسارات منها.
راجع قسم “دوال الاستبطان” للاطلاع على تفاصيل الدوال المستخدمة لفحص محتويات عمود JSON.
في الذاكرة، تكون بنية البيانات المشتركة مجرد عمود فرعي من النوع Map(String, String) يخزّن ربطًا بين مسار JSON مُسطَّح وقيمة مُرمَّزة ترميزًا ثنائيًا.
ولاستخراج عمود فرعي لمسار منه، نمرّ ببساطة على جميع الصفوف في عمود Map هذا ونحاول العثور على المسار المطلوب وقيمه.
في جداول MergeTree، نُخزّن البيانات في أجزاء بيانات تحتفظ بكل شيء على القرص (محليًا أو عن بُعد). ويمكن تخزين البيانات على القرص بطريقة تختلف عن تخزينها في الذاكرة.
يوجد حاليًا 3 تنسيقات serialization مختلفة لبنية البيانات المشتركة في أجزاء بيانات MergeTree: map وmap_with_buckets
وadvanced.
يخضع إصدار serialization للتحكم عبر إعدادات MergeTree
object_shared_data_serialization_version
وobject_shared_data_serialization_version_for_zero_level_parts
(جزء المستوى الصفري هو الجزء الذي يُنشأ عند insert البيانات إلى الجدول، وخلال merges تكون الأجزاء ذات مستويات أعلى).
ملاحظة: لا يُدعَم تغيير serialization لبنية البيانات المشتركة إلا
مع v3 object serialization version
في إصدار التسلسل map، تُسلسَل البيانات المشتركة كعمود واحد من النوع Map(String, String)، تمامًا كما تُخزَّن في
الذاكرة. لقراءة العمود الفرعي للمسار من هذا النوع من التسلسل، يقرأ ClickHouse عمود Map بالكامل ثم
يستخرج المسار المطلوب في الذاكرة.
يكون هذا التسلسل فعّالًا لكتابة البيانات وقراءة عمود JSON بالكامل، لكنه ليس فعّالًا لقراءة الأعمدة الفرعية للمسارات.
في إصدار تسلسل map_with_buckets، تُسلسَل البيانات المشتركة إلى N أعمدة (“حاويات”) من النوع Map(String, String).
ويحتوي كل bucket من هذه الحاويات على مجموعة فرعية فقط من المسارات. لقراءة عمود فرعي لمسار من هذا النوع من التسلسل، يقرأ ClickHouse
عمود Map بالكامل من bucket واحد ثم يستخرج المسار المطلوب في الذاكرة.
يكون هذا التسلسل أقل كفاءة عند كتابة البيانات وقراءة عمود JSON بالكامل، لكنها أكثر كفاءة عند قراءة الأعمدة الفرعية للمسارات
لأنها لا تقرأ البيانات إلا من الحاويات المطلوبة.
يُتحكَّم في عدد الحاويات N بواسطة إعدادات MergeTree object_shared_data_buckets_for_compact_part (8 افتراضيًا)
وobject_shared_data_buckets_for_wide_part (32 افتراضيًا).
والحد الأقصى المسموح به لكلا الإعدادين هو 256.
في إصدار التسلسل advanced، تُسلسَل البيانات المشتركة ضمن بنية بيانات خاصة تُحسِّن إلى أقصى حد أداء
قراءة الأعمدة الفرعية للمسارات، وذلك عبر تخزين بعض المعلومات الإضافية التي تتيح قراءة بيانات المسارات المطلوبة فقط.
كما يدعم هذا التسلسل أيضًا الحاويات، بحيث تحتوي كل حاوية على مجموعة فرعية فقط من المسارات.
يُعد هذا التسلسل غير فعّال نسبيًا عند كتابة البيانات (لذلك لا يُنصح باستخدامه مع الأجزاء ذات المستوى الصفري)، كما أن قراءة عمود JSON بالكامل أقل كفاءةً قليلًا مقارنةً بتسلسل map، لكنه فعّال جدًا عند قراءة الأعمدة الفرعية للمسارات.
ملاحظة: بسبب تخزين بعض المعلومات الإضافية داخل بنية البيانات، يكون حجم التخزين على القرص أكبر مع هذا التسلسل مقارنةً
بتسلسلي map وmap_with_buckets.
للاطلاع على نظرة عامة أكثر تفصيلًا حول تسلسلات البيانات المشتركة الجديدة وتفاصيل التنفيذ، اقرأ منشور المدونة.
التحكّم في عدد المسارات الديناميكية داخل JSON في أجزاء MergeTree
max_dynamic_paths داخل تعريف النوع JSON.
لكن تغيير max_dynamic_paths للأعمدة الحالية يتطلّب تشغيل ALTER TABLE <table> MODIFY COLUMN <column> JSON(max_dynamic_paths=K)، مما يبدأ عملية mutation في الخلفية تعيد كتابة جميع الأجزاء الموجودة.
وقد تكون هذه العملية ثقيلة جدًا، ويمكن أن تؤثر في أداء الخادم حتى اكتمالها. ولتجنّب ذلك، يمكنك استخدام هذه الإعدادات الثلاثة التي تساعدك على تغيير حدّ المسارات الديناميكية في جداول MergeTree لأجزاء البيانات الجديدة:
merge_max_dynamic_subcolumns_in_wide_part- إعداد في MergeTree يحدّ من عدد الأعمدة الفرعية الديناميكية لكل عمود JSON أثناء merge إلى جزء بيانات Wide.merge_max_dynamic_subcolumns_in_compact_part- إعداد في MergeTree يحدّ من عدد الأعمدة الفرعية الديناميكية لكل عمود JSON أثناء merge إلى جزء بيانات Compact.max_dynamic_subcolumns_in_json_type_parsing- إعداد session يحدّ من عدد الأعمدة الفرعية الديناميكية لكل عمود JSON أثناء parsing بيانات JSON إلى عمود JSON.
max_dynamic_paths، حتى إذا كانت قيم الإعدادات المذكورة أعلى.
دوال الاستبطان
JSONAllPathsJSONAllPathsWithTypesJSONAllValuesJSONDynamicPathsJSONDynamicPathsWithTypesJSONSharedDataPathsJSONSharedDataPathsWithTypesdistinctDynamicTypesdistinctJSONPaths and distinctJSONPathsAndTypes
2020-01-01:
Query
Response
Query
Response
ALTER MODIFY COLUMN إلى النوع JSON
JSON الجديد. حاليًا، لا يُدعَم ALTER إلا عند التحويل من النوع String.
مثال
Query
Response
تلميحات الأنواع الكسولة (تجريبية)
هذه الميزة تجريبية، وتتطلب أن يكون الإعداد
allow_experimental_json_lazy_type_hints مُمكّنًا.ALTER TABLE ... MODIFY COLUMN، يعيد ClickHouse عادةً كتابة جميع أجزاء البيانات لتطبيق تلميحات الأنواع الجديدة وتخزينها فعليًا. وقد تكون هذه العملية باهظة التكلفة جدًا للجداول التي تحتوي على كميات كبيرة من البيانات التاريخية (مئات التيرابايتات).
تتيح تلميحات الأنواع الكسولة إضافة تلميحات الأنواع كعملية تقتصر على البيانات الوصفية فقط، من دون إعادة كتابة البيانات الحالية:
- الأجزاء القديمة: تُطبَّق تلميحات الأنواع وقت الاستعلام عبر التحويل من
Dynamicإلى النوع المشار إليه - الأجزاء الجديدة: تُطبَّق تلميحات الأنواع وتُخزَّن فعليًا أثناء عمليات
INSERT - عمليات الدمج: تُطبَّق تلميحات الأنواع وتُخزَّن فعليًا عند دمج الأجزاء
تمكين تلميحات الأنواع الكسولة
مثال
Query
Response
التحقق من عدم حدوث أي mutation
ALTER قد اكتملت من دون حدوث mutation عبر فحص جدول system.mutations:
تجسيد تلميح الأنواع
- انتظار عمليات الدمج في الخلفية: سيعمل ClickHouse تلقائيًا على تجسيد تلميح الأنواع عند دمج الأجزاء
- فرض الدمج: استخدم
OPTIMIZE TABLE test_lazy FINALلدمج جميع الأجزاء فورًا - إعادة كتابة الأجزاء: استخدم
ALTER TABLE test_lazy REWRITE PARTSلإعادة كتابة الأجزاء باستخدام البيانات الوصفية الجديدة
القيود
- هذه الميزة تجريبية وقد تتغير في الإصدارات المستقبلية
- قد يترتب على تحويل الأنواع وقت الاستعلام عبء كبير على الأداء مقارنةً بالأنواع المُخزَّنة مسبقًا، خاصةً مع كائنات JSON الكبيرة
- لا تنطبق هذه الميزة إلا عند تعديل
typed_paths(تلميحات الأنواع)؛ أما معلمات JSON الأخرى مثلmax_dynamic_pathsأوSKIPأوSKIP REGEXPفما تزال تتطلب إجراء mutations
مقارنة قيم نوع JSON
Query
Response
Variant.
فهارس تخطي البيانات في JSON
JSON بثلاث طرق:
- فهارس لأعمدة فرعية محددة — أنشئ فهرس تخطٍّ قياسيًا لمسار JSON معروف، تمامًا كما تفعل مع عمود عادي. يفهرس هذا القيم الموجودة في ذلك المسار.
- فهارس قائمة على المسار باستخدام
JSONAllPaths— فهرسة مجموعة المسارات الموجودة في كل حبيبة لتخطي الحبيبات التي يستحيل أن تحتوي على المسار المطلوب في الاستعلام. - فهارس قائمة على القيم باستخدام
JSONAllValues— فهرسة جميع القيم عبر كل مسارات JSON باستخدام فهرس نصي لتسريع البحث النصي الكامل في أي عمود JSON فرعي باستخدام فهرس واحد.
فهارس على أعمدة فرعية محددة
minmax، set، bloom_filter، tokenbf_v1، ngrambf_v1، إلخ).
هناك طريقتان للإشارة إلى عمود فرعي في JSON داخل تعبير الفهرس:
- مسار محدد النوع مُعلَن في تلميح الأنواع لـ JSON — يُوصَل إليه بالاسم مباشرةً:
json.a. - مسار ديناميكي مع تحويل نوع صريح — استخدم صياغة التحويل
:::json.b::String.
json.a || json.b::String.
مثال
Query
minmax على العمود الفرعي data.sensor_id ذي النوع المحدد نطاق الفحص ليقتصر على الحبيبات المطابقة:
Query
Response
bloom_filter أيضًا على العمود الفرعي المُحوَّل data.location::String:
Query
Response
فهارس قائمة على المسارات باستخدام JSONAllPaths
JSON باستخدام الدالة JSONAllPaths.
ويعمل ذلك بطريقة مشابهة لإنشاء فهارس التخطي على أعمدة Map عبر mapKeys — إذ يخزّن الفهرس مجموعة مسارات JSON الموجودة في كل حبيبة، ويستخدمها لتخطي الحبيبات التي لا يمكن أن تحتوي على المسار المطلوب في الاستعلام.
أنواع الفهارس المدعومة
JSONAllPaths مع أنواع فهارس التخطي التالية:
bloom_filter— يدعمequalsوinوIS NOT NULL.tokenbf_v1— يدعمequalsوIS NOT NULL.ngrambf_v1— يدعمequalsوIS NOT NULL.text(فهرس مقلوب) — يدعمequalsوinوIS NOT NULL.
مثال
Query
EXPLAIN indexes = 1 للتحقق من استخدام فهرس التخطي. عندما يكون المسار موجودًا في جزء واحد فقط، يتجاوز الفهرس الجزء الآخر:
Query
Response
Query
Response
IS NOT NULL أيضًا الفهرس — إذ يتجاوز الحبيبات التي يكون فيها المسار غير موجود (لأن القيمة ستكون NULL):
Query
Response
كيف يعمل
JSONAllPaths(json_column) قيمة Array(String) تحتوي على جميع المسارات الموجودة في قيمة JSON.
يخزّن فهرس التخطي سلاسل المسارات هذه في بنية البيانات الخاصة به (bloom filter أو inverted index).
عندما يطبّق الاستعلام عامل تصفية على json.some.path، يتحقق الفهرس مما إذا كانت السلسلة "some.path" موجودة في الفهرس لكل حبيبة، ويتجاوز الحبيبات التي لا تحتوي عليها.
الأمان عند غياب المسارات
NULLمع النوعDynamic(مثلjson.path) والأعمدة الفرعية من النوعNullable(مثلjson.path.:Int64) — تُرجِع المقارنات معNULLدائمًا false، لذا يكون skipping آمنًا.- القيمة الافتراضية للنوع في تعبيرات
CASTغيرNullable(مثلjson.path::Int64الذي ينتج0عند غياب المسار) — لا يكون skipping آمنًا إلا عندما تختلف القيمة المُقارَنة عن القيمة الافتراضية. ويتولى الفهرس هذا التمييز تلقائيًا.
البحث النصي الكامل باستخدام JSONAllValues
JSONAllValues.
تُرجع JSONAllValues جميع القيم من عمود JSON بصيغة Array(String)، ويمكن فهرستها باستخدام فهرس نصي.
ويغطي فهرس واحد على JSONAllValues(json_column) جميع مسارات JSON، مما يتيح البحث النصي الكامل في أي عمود فرعي دون الحاجة إلى إنشاء فهارس منفصلة لكل مسار.
راجع الفهارس المستندة إلى القيم باستخدام JSONAllValues في توثيق الفهارس النصية للاطلاع على التفاصيل والأمثلة.
نصائح لتحسين استخدام نوع JSON
JSON وتحميل البيانات فيه، ضع النصائح التالية في اعتبارك:
- افحص بياناتك وحدّد أكبر عدد ممكن من تلميحات المسارات مع أنواعها. فهذا يجعل التخزين والقراءة أكثر كفاءة بدرجة كبيرة.
- فكّر في المسارات التي ستحتاج إليها والمسارات التي لن تحتاج إليها أبدًا. حدّد المسارات التي لن تحتاج إليها في قسم
SKIP، وفي قسمSKIP REGEXPعند الحاجة. سيؤدي ذلك إلى تحسين التخزين. - لا تضبط المعلَمة
max_dynamic_pathsعلى قيم مرتفعة جدًا، لأن ذلك قد يقلّل من كفاءة التخزين والقراءة. ورغم أن ذلك يعتمد بدرجة كبيرة على معلمات النظام مثل الذاكرة وCPU وما إلى ذلك، فإن القاعدة العامة هي ألا تضبطmax_dynamic_pathsعلى قيمة تتجاوز 10 000 لتخزين نظام الملفات المحلي و1024 لتخزين نظام الملفات البعيد.