Map(LowCardinality(String), String). ويدعم ClickHouse أيضًا نوع JSON محدَّد الأنواع بشكل صارم، كما يوفّر ClickStack دعمًا تجريبيًا لاستخدامه بدلًا من Map.
بالنسبة إلى أعباء عمل observability المعتادة، نوصي بالإبقاء على المخطط الافتراضي المستند إلى Map. يتوفر نوع JSON للمستخدمين الذين يريدون تقييمه على أعباء عمل تتضمن مجموعة صغيرة ومستقرة من مفاتيح السمات، لكنه ليس المخطط الموصى به للاستخدام العام.
لماذا يُعد Map الخيار الافتراضي الموصى به
Map(LowCardinality(String), String) المفاتيح والقيم ضمن بنية واحدة. وكان العيب التقليدي في Map هو أن قراءة مفتاح واحد كانت تتطلب قراءة عمود map بالكامل. لكن هذا لم يعد صحيحًا: إذ يدعم ClickHouse الآن التسلسل المقسّم إلى حاويات لـ map، الذي يقسّم map إلى حاويات بحيث لا تقرأ الاستعلامات إلا الحاويات التي تحتاج إليها. وعند دمج ذلك مع الفهارس النصية على مفاتيح map وقيمه، وهي الطريقة التي جرى بها إعداد المخطط الافتراضي لـ ClickStack، يصبح Map انتقائيًا وسريعًا عند القراءة، من دون أي تكلفة إضافية عند الاستيعاب بسبب المفاتيح الجديدة.
عمليًا، يعني ذلك ما يلي:
- استقرار تكلفة الاستيعاب مع زيادة عدد المفاتيح. لا تؤدي إضافة مفتاح سمة جديد إلى تغيير تخطيط الأعمدة على القرص أو إنشاء ملفات أعمدة جديدة. وتظل تكلفة الاستيعاب محكومة بحجم البيانات، لا بكاردينالية المفاتيح.
- عدم تضخم البيانات الوصفية. لا يرتبط عدد ملفات الأعمدة على القرص بعدد مفاتيح السمات الفريدة.
- عمليات lookup انتقائية عبر الفهارس. توفّر الفهارس النصية على مفاتيح map وقيمه عمليات lookup مباشرة من دون فحص كل صف.
- سلوك متوقع عند معدلات النقل العالية. يتعامل Map مع مجموعات السمات غير المقيّدة بمخطط، والتي تصل على دفعات ومتقلبة، وهو أمر شائع في tracing والسجلات، من دون عبء إضافي لكل مفتاح.
لماذا لا نستخدم JSON افتراضيًا
JSON نهجًا مختلفًا: ففي وقت الإدراج، ينشئ ClickHouse ديناميكيًا عمودًا فرعيًا مخصصًا وذا نوع محدد بدقة لكل path يرصده. وعند القراءة، يبدو هذا جذابًا لأن الأعمدة الفرعية المطلوبة فقط هي التي تُقرأ، وتُحفَظ الأنواع، ولا تكون هناك حاجة إلى تحويل الأنواع على مستوى query.
لكن المقايضة تظهر في وقت الاستيعاب. فإِنشاء عدد كبير من الأعمدة الفرعية الديناميكية وإدارتها يضيف كلفةً إضافية وقت الكتابة ويزيد من تعقيد البيانات الوصفية. وفي أحمال observability، التي تتضمن عادةً مجموعات attribute كبيرة جدًا أو عالية الديناميكية ومعدل معدل استيعاب البيانات مرتفعًا، تكون هذه الكلفة الإضافية كبيرة. ويمكن للحد max_dynamic_paths أن يخفف من هذا الأثر عبر تمرير paths الإضافية إلى عمود مشترك، لكن الوصول إلى العمود المشترك أبطأ من الأعمدة الفرعية المخصصة، مما يقلص ميزة وقت القراءة التي كانت أصلًا سبب استخدام JSON.
ومع إزالة bucketed map serialization لمعظم الكلفة الإضافية التاريخية لوقت القراءة في Map، لم تعد ميزة وقت القراءة في JSON تفوق كلفته وقت الاستيعاب بالنسبة إلى أحمال observability المعتادة.
متى قد تفكر في JSON
- تكون مجموعة مفاتيح السمات صغيرة ومستقرة، أي أنك لا ترى آلاف المفاتيح الفريدة، ونادرًا ما تظهر مفاتيح جديدة.
- يكون معدل استيعاب البيانات محدودًا مقارنةً بدرجة cardinality للسمات.
- تريد وصولًا قويَّ التحديد بالأنواع إلى السمات من دون عمليات CAST وقت الاستعلام، (فتبقى الأرقام أرقامًا، وتبقى القيم المنطقية قيمًا منطقية).
- تكون مستعدًا لتشغيل ميزة تجريبية في ClickStack وتقبّل أن هذا التكامل قد يتغيّر.
Map.
حالة Beta
2.0.4.
تمكين دعم JSON
Map، اضبط متغيرات البيئة التالية.
Managed ClickStack
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' في المجمّع. على سبيل المثال:
ClickStack مفتوح المصدر
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' في أي Deployment يتضمّن المجمّع، وعيّن BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true في طبقة تطبيق HyperDX لكي يتمكّن من الاستعلام عن المخططات من نوع JSON.
على سبيل المثال:
الترحيل من مخطط قائم على Map إلى JSON
1
أوقف OTel المجمّع
2
أعد تسمية الجداول الحالية وحدّث المصادر
أعد تسمية الجداول الحالية وحدّث مصادر البيانات في HyperDX.على سبيل المثال:3
انشر OTel المجمّع
انشر OTel المجمّع مع تعيينOTEL_AGENT_FEATURE_GATE_ARG.4
أعد تشغيل حاوية HyperDX مع دعم مخطط JSON
5