Skip to main content
نوع العمود JSON جاهز للاستخدام في بيئات الإنتاج بدءًا من ClickHouse 25.3+. ولا يُنصح باستخدام الإصدارات الأقدم في بيئات الإنتاج.
تصل بياناتك بصيغة JSON. يوفّر ClickHouse عدة طرق لتخزينها، بدءًا من الأعمدة ذات الأنواع المحددة بالكامل وصولًا إلى String الخام. ويعتمد الاختيار المناسب على مدى ثبات مخططك، وما إذا كنت تحتاج إلى استعلامات على مستوى الحقول. النطاق: تغطي هذه الصفحة قرارات تصميم المخطط الخاصة بتخزين بيانات JSON. ولا تغطي تنسيقات إدخال/إخراج JSON، أو دوال JSON، أو بنية الاستعلام. وللاطلاع على مزيد من المعلومات حول نوع العمود JSON نفسه، راجع استخدم JSON حيثما كان مناسبًا. يفترض: الإلمام بـ إنشاء جداول ClickHouse، وأساسيات MergeTree، وبنية أنواع الأعمدة.

قرار سريع

  • إذا كان لكل حقل نوع معروف ومستقر، وكان المخطط نادر التغيّر أعمدة محددة النوع
  • إذا كانت معظم الحقول مستقرة، لكن بعض الأجزاء ديناميكيًا أو غير متوقع هجين (أعمدة محددة النوع + JSON)
  • إذا كانت البنية بأكملها ديناميكية، مع مفاتيح تظهر وتختفي بين السجلات عمود JSON أصلي
  • إذا كانت الحقول الديناميكية أزواج مفتاح-قيمة ذات نوع قيمة متسق (مثل tags النصية وmetrics الرقمية) Map بدلًا من JSON
  • إذا كنت تخزّن وتسترجع blob ‏JSON فقط من دون استعلامات على مستوى الحقل تخزين String غير مُفسَّر
لا تخلط بين تنسيق JSON ونوع عمود JSON. يمكنك إدراج بيانات منسّقة بصيغة JSON (عبر JSONEachRow وغيرها) في أعمدة محددة النوع من دون استخدام نوع العمود JSON على الإطلاق. القرار هنا يتعلق بأنواع الأعمدة، لا بتنسيقات الإدخال.

تفاصيل النهج

أعمدة محددة النوع

متى تُستخدم: تكون بنية JSON معروفة بالكامل وقت التصميم. ولا تتغير الحقول والأنواع من سجل إلى آخر. ويمكن حتى تمثيل البُنى المتداخلة المعقدة (مثل مصفوفات الكائنات والخرائط المتداخلة) باستخدام الأنواع Array وTuple وNested. الاعتبارات: تتطلب تغييرات المخطط استخدام ALTER TABLE. كما تُهمَل الحقول غير المتوقعة بصمت عند الإدراج ما لم يتم تحديث المخطط.
الإعداد
التحقق
انتبه إلى
  • إذا أدرجت بيانات JSON باستخدام JSONEachRow وكان JSON يحتوي على حقول غير موجودة في المخطط، فإن ClickHouse يتجاهلها بصمت افتراضيًا. اضبط input_format_skip_unknown_fields على 0 إذا كنت تريد ظهور أخطاء بدلًا من ذلك.

هجين (أعمدة محددة النوع + JSON)

متى يُستخدم: عندما تكون هناك مجموعة أساسية مستقرة من الحقول (الطوابع الزمنية، والمعرّفات، ورموز الحالة)، بينما يكون جزء من الحمولة ديناميكيًا. فكّر في السمات المعرّفة من المستخدم، أو الوسوم، أو البيانات الوصفية، أو حقول الامتداد التي تختلف من سجل إلى آخر. المفاضلات: تحصل على الأداء الكامل في الأعمدة محددة النوع، مع مرونة في عمود JSON. لكن عمود JSON يظل يضيف عبئًا عند insert وتكلفة تخزين لجزئه الديناميكي.
الإعداد
التحقق
انتبه إلى
  • استخدم تلميحات الأنواع لمسارات JSON التي تعرفها مسبقًا. تتجاوز هذه التلميحات عمود التمييز وتخزّن المسار مثل أي عمود محدد النوع عادي، بالأداء نفسه ومن دون عبء إضافي.
  • استخدم SKIP أو SKIP REGEXP للمسارات التي لا تستعلم عنها مطلقًا (مثل بيانات debug الوصفية ومعرّفات tracing الداخلية) لتوفير مساحة التخزين وتقليل عدد الأعمدة الفرعية.
  • اضبط max_dynamic_paths بما يتناسب مع عدد المسارات الفريدة التي تستعلم عنها فعليًا. تعمل القيمة الافتراضية (1024) في معظم الحالات. خفّضها إذا كان القسم الديناميكي لديك محدودًا.
  • لا تضبط max_dynamic_paths على قيمة تتجاوز 10,000. فالقيم المرتفعة تزيد استهلاك الموارد وتقلل الكفاءة.
المفاتيح المنقوطةتُعامل المفاتيح التي تحتوي على نقاط (مثل http.status_code) على أنها مسارات متداخلة افتراضيًا، لذا يُخزَّن {"http.status_code": 200} بالطريقة نفسها التي يُخزَّن بها {"http": {"status_code": 200}}. وهذا شائع في سمات OTel. استخدم تلميحات الأنواع للتحكم في كيفية تخزين المسارات المنقوطة، أو فعّل json_type_escape_dots_in_keys (25.8+).

عمود JSON الأصلي

متى يُستخدم: عندما تكون البنية غير قابلة للتنبؤ فعلًا، مع مفاتيح تظهر وتختفي بين السجلات. مثل المخططات التي ينشئها المستخدمون، أو أنظمة الملحقات، أو استيعاب البيانات في data lake عندما لا تتحكم في المخطط upstream. المفاضلات: تكون عمليات الإدراج أبطأ من الأعمدة محددة النوع. كما أن قراءات الكائن الكامل أبطأ من String. وهناك عبء تخزيني إضافي ناتج عن إدارة الأعمدة الفرعية. لكنه يعمل جيدًا مع الاستعلامات على مستوى الحقول لمسارات محددة.
الإعداد
استخدم تنسيق JSONAsObject عند إدراج مستندات JSON كاملة في عمود JSON. فهو يتعامل مع كل سطر إدخال على أنه كائن JSON كامل يُربَط بالعمود.التحقق
انتبه إلى
  • من دون تلميحات للأنواع، يستنتج ClickHouse الأنواع لكل مسار استنادًا إلى أول القيم التي يراها. فإذا وصلت score على شكل "10" (سلسلة نصية) في سجل، و10 (عدد صحيح) في سجل آخر، فسيُنشئ المسار discriminator column وتصبح الاستعلامات أبطأ. أضف تلميحات للمسارات ذات الأنواع المعروفة.
  • عندما يتجاوز عدد المسارات max_dynamic_paths، تنتقل قيم overflow إلى بنية بيانات مشتركة مع تراجع في query performance. راقب ذلك باستخدام JSONDynamicPaths()، وأبقِ الحد أقل من 10,000.
  • يدعم كل مسار ديناميكي حتى max_dynamic_types (القيمة الافتراضية 32) من data types المميزة. وإذا تجاوز مسار واحد هذا الحد، فستعود الأنواع الإضافية تلقائيًا إلى تخزين متغير مشترك. ونادرًا ما يكون هذا مهمًا إلا إذا كانت بياناتك تحتوي على أنواع شديدة التباين للحقل نفسه.

تخزين String غير مُفسَّر

متى يُستخدم: تُخزَّن مستندات JSON وتُسترجَع كاملةً، ثم تُمرَّر إلى تطبيق، أو تُؤرشف، أو تُوجَّه إلى أنظمة لاحقة. لا توجد تصفية على مستوى الحقول أو تجميع داخل ClickHouse. المفاضلات: أسرع عمليات إدراج وأبسط مخطط. لا توجد استعلامات على مستوى الحقول من دون تحليل وقت التشغيل (عائلة JSONExtract)، وهذا يكون بطيئًا عند التوسّع.
الإعداد
التحقق
انتبه إلى
  • إذا تغيّرت المتطلبات واحتجت لاحقًا إلى استعلامات على مستوى الحقول، فستحتاج إلى إنشاء table جديدة تضم columns محددة النوع أو JSON columns، ثم backfill للبيانات. إذا كان هناك أي احتمال لأن تستعلم عن حقول منفردة، فابدأ باستخدام النهج الهجين بدلًا من ذلك.
  • تُحلِّل دوال JSONExtract السلسلة في كل query. هذا مقبول للاستكشاف المخصص، لكنه غير مناسب لـ dashboards في بيئة production أو workloads ذات QPS مرتفع.
  • فكّر في استخدام codecs للضغط (ZSTD) على عمود String إذا كانت payloads الخاصة بـ JSON كبيرة، إذ يضغطها بكفاءة.

المقارنة

متى يكون Map خيارًا أفضل

إذا كانت حقولك الديناميكية تتكوّن من أزواج مفتاح-قيمة متجانسة — أي إن جميع القيم من النوع نفسه — فإن Map(String, T) أبسط وأكثر كفاءة من عمود JSON. ومن الأمثلة الشائعة: الوسوم النصية (Map(String, String))، والمقاييس العددية (Map(String, Float64))، أو مفاتيح تفعيل الميزات (Map(String, Bool)).
يدعم Map التصفية على مستوى المفاتيح (tags['env'] = 'prod')، وتكلفة تخزينه أقل من JSON، كما يتجنب الكلفة الإضافية للأعمدة الفرعية في نوع JSON. لاحظ أن عمليات البحث عن المفاتيح تفحص الخريطة خطيًا افتراضيًا — وهذا مناسب لمجموعات الوسوم الصغيرة، ولكن إذا كانت خرائط Map تحتوي على أكثر من 100 مفتاح، ففكّر في استخدام تسلسل with_buckets. استخدم JSON عندما تكون القيم من أنواع مختلطة أو عندما تكون البنية متداخلة — واستخدم Map عندما تكون البيانات أزواج مفتاح-قيمة مسطحة ذات نوع قيم موحّد.
آخر تعديل في ٢٣ يوليو ٢٠٢٦