يخزّن المخطط الافتراضي في ClickStack سمات resource وscope وlog وspan في أعمدة Map(LowCardinality(String), String). ويدعم ClickHouse أيضًا نوع JSON محدَّد الأنواع بشكل صارم، كما يوفّر ClickStack دعمًا تجريبيًا لاستخدامه بدلًا من Map.
بالنسبة إلى أعباء عمل observability المعتادة، نوصي بالإبقاء على المخطط الافتراضي المستند إلى Map. يتوفر نوع JSON للمستخدمين الذين يريدون تقييمه على أعباء عمل تتضمن مجموعة صغيرة ومستقرة من مفاتيح السمات، لكنه ليس المخطط الموصى به للاستخدام العام.
لماذا يُعد Map الخيار الافتراضي الموصى به
تهيمن على بيانات observability سمات مثل سمات المورد، وسمات النطاق، وسمات span وlog. وتكون هذه المجموعات عادةً كبيرة وعالية الكاردينالية، ويجري استيعابها بمعدل نقل مرتفع. ويُعد المخطط الذي تختاره لهذه السمات العامل الأهم في تكلفة الاستيعاب وتخطيط التخزين.
يخزّن 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.
ميزة تجريبية، وليست جاهزة لبيئات الإنتاجدعم نوع JSON في ClickStack هو ميزة تجريبية. ورغم أن نوع JSON نفسه جاهز لبيئات الإنتاج في ClickHouse 25.3+، فإن تكامله ضمن ClickStack لا يزال قيد التطوير النشط، وقد تكون له قيود، أو يتغير مستقبلًا، أو يحتوي على أخطاء.
يوفر ClickStack دعمًا تجريبيًا لنوع JSON بدءًا من الإصدار 2.0.4.
لاستخدام المخططات المعرّفة بنوع JSON بدلًا من المخططات الافتراضية المستندة إلى Map، اضبط متغيرات البيئة التالية.
| المتغير | يُضبط في | الغرض |
|---|
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' | OTel المجمّع | ينشئ مخططات في ClickHouse باستخدام نوع JSON. |
BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true | HyperDX (ClickStack UI) | يُمكّن طبقة التطبيق من الاستعلام عن المخططات المعرّفة بنوع JSON. ClickStack Open Source فقط. |
لتمكين دعم JSON في Managed ClickStack، تواصل مع فريق الدعم عبر support@clickhouse.com قبل تهيئة المجمّع. يجب أيضًا تمكين هذه الميزة في واجهة مستخدم ClickStack (HyperDX) ضمن ClickHouse Cloud.
عيّن OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' في المجمّع. على سبيل المثال:
docker run -e OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' -e CLICKHOUSE_ENDPOINT=${CLICKHOUSE_ENDPOINT} -e CLICKHOUSE_USER=default -e CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD} -p 8080:8080 -p 4317:4317 -p 4318:4318 clickhouse/clickstack-otel-collector:latest
عيّن OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' في أي Deployment يتضمّن المجمّع، وعيّن BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true في طبقة تطبيق HyperDX لكي يتمكّن من الاستعلام عن المخططات من نوع JSON.
على سبيل المثال:
docker run -e OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' -e OPAMP_SERVER_URL=${OPAMP_SERVER_URL} -e CLICKHOUSE_ENDPOINT=${CLICKHOUSE_ENDPOINT} -e CLICKHOUSE_USER=default -e CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD} -p 8080:8080 -p 4317:4317 -p 4318:4318 clickhouse/clickstack-otel-collector:latest
الترحيل من مخطط قائم على Map إلى JSON
التوافق العكسيإن نوع JSON غير متوافق عكسيًا مع المخططات الحالية القائمة على Map. يؤدي تمكين هذه الميزة إلى إنشاء جداول جديدة باستخدام النوع JSON، ويتطلب ترحيلاً يدويًا للبيانات.
للترحيل من المخططات الافتراضية المستندة إلى Map، اتبع الخطوات التالية:
أعد تسمية الجداول الحالية وحدّث المصادر
أعد تسمية الجداول الحالية وحدّث مصادر البيانات في HyperDX.على سبيل المثال:RENAME TABLE otel_logs TO otel_logs_map;
RENAME TABLE otel_metrics TO otel_metrics_map;
انشر OTel المجمّع
انشر OTel المجمّع مع تعيين OTEL_AGENT_FEATURE_GATE_ARG.أعد تشغيل حاوية HyperDX مع دعم مخطط JSON
export BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true
أنشئ مصادر بيانات جديدة
أنشئ مصادر بيانات جديدة في HyperDX تشير إلى جداول JSON.
ترحيل البيانات الحالية (اختياري)
لنقل البيانات القديمة إلى جداول JSON الجديدة:
INSERT INTO otel_logs SELECT * FROM otel_logs_map;
INSERT INTO otel_metrics SELECT * FROM otel_metrics_map;
يُوصى بهذا فقط لمجموعات البيانات التي يقل حجمها عن نحو 10 مليارات صف. البيانات المخزنة سابقًا باستخدام النوع Map لم تكن تحافظ على دقة الأنواع (إذ كانت جميع القيم من النوع Strings). ونتيجةً لذلك، ستظهر هذه البيانات القديمة كسلاسل نصية في المخطط الجديد إلى أن تنتهي صلاحيتها، ما يتطلب إجراء بعض تحويلات الأنواع في الواجهة الأمامية. أما البيانات الجديدة، فستُحفَظ أنواعها باستخدام النوع JSON.