Skip to main content
عميل JS الرسمي للاتصال بـ ClickHouse. العميل مكتوب بلغة TypeScript ويوفر تعريفات أنواع لواجهة برمجة تطبيقات العميل العامة. لا يتضمن أي تبعيات، وهو مُحسَّن لتحقيق أقصى أداء، وقد اختُبر مع إصدارات وتكوينات مختلفة من ClickHouse (نشر محلي على عقدة واحدة، ونشر محلي على cluster، وClickHouse Cloud). تتوفر نسختان مختلفتان من العميل لبيئات مختلفة:
  • @clickhouse/client - Node.js only
  • @clickhouse/client-web - المتصفحات (Chrome/Firefox)، Cloudflare workers
عند استخدام TypeScript، تأكد من أن الإصدار لا يقل عن 4.5، إذ يتيح ذلك بنية import وexport المضمنة. الشيفرة المصدرية للعميل متاحة في مستودع ClickHouse-JS على GitHub.
مهارات AI Agentيأتي عميل JS مزودًا بمهارات AI Agent يمكن أن تساعد وكلاء البرمجة على العمل مع العميل. ثبّتها باستخدام:

متطلبات البيئة (node.js)

يجب أن يكون Node.js متاحًا في البيئة لتشغيل العميل. العميل متوافق مع جميع إصدارات Node.js التي لا تزال مدعومة. وبمجرد أن يقترب أحد إصدارات Node.js من نهاية دورة الدعم، يتوقف العميل عن دعمه لأنه يُعد قديمًا وغير آمن. يدعم العميل حاليًا إصدارات Node.js التالية:

متطلبات البيئة (الويب)

يُختبَر إصدار الويب من العميل رسميًا على أحدث إصدارات متصفحات Chrome وFirefox، ويمكن استخدامه كتبعية، على سبيل المثال، في تطبيقات React/Vue/Angular أو في Cloudflare workers.

التثبيت

لتثبيت أحدث إصدار مستقر من عميل Node.js، شغّل:
تثبيت إصدار الويب:

التوافق مع ClickHouse

من المرجّح أن يعمل العميل أيضًا مع الإصدارات الأقدم؛ ومع ذلك، فهذا الدعم يُقدَّم على أساس بذل أفضل جهد وليس مضمونًا. إذا كان لديك إصدار من ClickHouse أقدم من 23.3، فيُرجى الرجوع إلى سياسة الأمان في ClickHouse والنظر في الترقية.

أمثلة

نسعى إلى تغطية سيناريوهات متنوعة لاستخدام العميل من خلال الأمثلة الموجودة في مستودع العميل. يمكن الاطلاع على النظرة العامة في README الخاص بالأمثلة. إذا كان هناك شيء غير واضح أو مفقود في الأمثلة أو في الوثائق التالية، فلا تتردد في التواصل معنا.

واجهة برمجة تطبيقات العميل

يجب أن تكون معظم الأمثلة متوافقة مع كلٍّ من إصدار Node.js وإصدار الويب من العميل، ما لم يُذكر صراحةً خلاف ذلك.

إنشاء مثيل للعميل

يمكنك إنشاء أي عدد تحتاج إليه من مثيلات العميل باستخدام دالة المصنع createClient:
إذا كانت بيئتك لا تدعم وحدات ESM، يمكنك استخدام صيغة CJS بدلًا منها:
يمكن تهيئة مثيل العميل مسبقًا عند إنشائه.

التهيئة

عند إنشاء مثيل عميل، يمكن تعديل إعدادات الاتصال التالية:

معلمات التكوين الخاصة بـ Node.js

إعداد URL

سيؤدي إعداد URL دائمًا إلى تجاوز القيم المضمّنة في الشيفرة، وسيُسجَّل تحذير في هذه الحالة.
يمكن إعداد معظم معلمات مثيل العميل باستخدام URL. يكون تنسيق URL على النحو التالي: http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]. في معظم الحالات، يعكس اسم معلمة معيّنة مسارها في واجهة خيارات config، مع بعض الاستثناءات القليلة. المعلمات التالية مدعومة:
  • (1) بالنسبة إلى القيم المنطقية، تكون القيم الصالحة true/1 و false/0.
  • (2) أي معلمة تبدأ بـ clickhouse_setting_ أو ch_ ستُزال منها هذه البادئة، وسيُضاف الباقي إلى clickhouse_settings الخاص بالعميل. على سبيل المثال، ?ch_async_insert=1&ch_wait_for_async_insert=1 سيكون مماثلًا لما يلي:
ملاحظة: يجب تمرير القيم المنطقية لـ clickhouse_settings بصيغة 1/0 في عنوان URL.
  • ‏(3) مماثل لـ (2)، ولكن لإعداد http_header. على سبيل المثال، يُعد ?http_header_x-clickhouse-auth=foobar مكافئًا لـ:

الاتصال

جهّز تفاصيل الاتصال الخاصة بك

للاتصال بـ ClickHouse باستخدام HTTP(S)، تحتاج إلى المعلومات التالية: تتوفر تفاصيل خدمة ClickHouse Cloud الخاصة بك في ClickHouse Cloud console. حدِّد خدمة ثم انقر على Connect:
زر Connect لخدمة ClickHouse Cloud
اختر HTTPS. ستظهر تفاصيل الاتصال في مثال لأمر curl.
تفاصيل اتصال HTTPS لخدمة ClickHouse Cloud
إذا كنت تستخدم ClickHouse مُدارًا ذاتيًا، فسيُحدِّد مسؤول ClickHouse لديك تفاصيل الاتصال.

نظرة عامة على الاتصال

يدعم العميل الاتصال عبر بروتوكول HTTP أو HTTPS. ويجري العمل حاليًا على دعم RowBinary، راجع المشكلة ذات الصلة. يوضح المثال التالي كيفية إعداد اتصال بـ ClickHouse Cloud. ويفترض أن قيمتَي url (بما في ذلك البروتوكول والمنفذ) وpassword محددتان عبر متغيرات البيئة، وأن المستخدم default هو المستخدم المعتمد. مثال: إنشاء مثيل العميل في Node.js باستخدام متغيرات البيئة للتهيئة.
يحتوي مستودع العميل على أمثلة متعددة تستخدم متغيرات البيئة، مثل إنشاء جدول في ClickHouse Cloud، واستخدام عمليات الإدراج غير المتزامنة، وغيرها الكثير.

مجمع الاتصالات (لـ Node.js فقط)

لتجنّب العبء الإضافي الناتج عن إنشاء اتصال مع كل طلب، ينشئ العميل مجمعًا من الاتصالات إلى ClickHouse لإعادة استخدامها، بالاستفادة من آلية Keep-Alive. تكون Keep-Alive مفعّلة افتراضيًا، ويُضبط حجم مجمع الاتصالات على 10، ولكن يمكنك تغييره باستخدام خيار الإعداد max_open_connections. لا يوجد ما يضمن استخدام الاتصال نفسه من مجمع الاتصالات في الاستعلامات اللاحقة، ما لم يضبط المستخدم max_open_connections: 1. نادرًا ما تكون هناك حاجة إلى ذلك، لكنه قد يكون مطلوبًا في الحالات التي يستخدم فيها المستخدمون الجداول المؤقتة. انظر أيضًا: إعداد Keep-Alive.

معرّف الاستعلام

ستوفّر كل طريقة تُرسل استعلامًا أو عبارة (command, exec, insert, select) قيمة query_id في النتيجة. يُسنِد العميل هذا المعرّف الفريد لكل استعلام، وقد يكون مفيدًا لاسترجاع البيانات من system.query_log، إذا كان ذلك مفعّلًا في إعدادات الخادم، أو لإلغاء الاستعلامات طويلة التشغيل (راجع المثال). وإذا لزم الأمر، يمكن للمستخدم تجاوز query_id ضمن params لطرق command/query/exec/insert.
إذا كنت تتجاوز المعامل query_id، فعليك التأكد من فرادته في كل استدعاء. ويُعدّ معرّف UUID عشوائي خيارًا جيدًا.

المعلمات الأساسية لجميع طرق العميل

توجد عدة معلمات يمكن تطبيقها على جميع طرق العميل (query/command/insert/exec).

طريقة الاستعلام

تُستخدم هذه الطريقة لمعظم العبارات التي يمكن أن تُرجع استجابة، مثل SELECT، أو لإرسال عبارات DDL مثل CREATE TABLE، ويجب انتظار اكتمالها. ويُفترض أن يستهلك التطبيق مجموعة النتائج المُعادة.
توجد طريقة مخصّصة insert لإدراج البيانات، وcommand لعبارات DDL.
راجع أيضًا: المعلمات الأساسية لجميع طُرق العميل.
لا تُحدِّد عبارة FORMAT في query، واستخدم المعامل format بدلًا من ذلك.

تجريدات مجموعة النتائج والصفوف

يوفّر ResultSet عدة طرق ميسّرة لمعالجة البيانات في تطبيقك. يعتمد تنفيذ ResultSet في Node.js على Stream.Readable داخليًا، بينما يستخدم إصدار الويب واجهة Web API ‏ReadableStream. يمكنك استهلاك ResultSet باستدعاء الطريقة text أو json على ResultSet، ما يحمّل مجموعة الصفوف كاملةً التي أعادها الاستعلام إلى الذاكرة. يجب أن تبدأ في استهلاك ResultSet في أسرع وقت ممكن، لأنه يُبقي تدفّق الاستجابة مفتوحًا، وبالتالي يُبقي الاتصال الأساسي مشغولًا. ولا يَخزّن العميل البيانات الواردة مؤقتًا، تجنبًا لاحتمال استهلاك التطبيق قدرًا مفرطًا من الذاكرة. بدلًا من ذلك، إذا كانت البيانات كبيرة جدًا بحيث لا يمكن تحميلها في الذاكرة دفعةً واحدة، يمكنك استدعاء الطريقة stream ومعالجة البيانات في وضع البث. في هذه الحالة، سيُحوَّل كل جزء من أجزاء الاستجابة إلى مصفوفات صغيرة نسبيًا من الصفوف، جزءًا تلو الآخر (ويعتمد حجم هذه المصفوفة على حجم الجزء الذي يستقبله العميل من الخادم، والذي قد يختلف، وكذلك على حجم الصف الواحد). يُرجى الرجوع إلى قائمة تنسيقات البيانات المدعومة لتحديد أفضل تنسيق للبث في حالتك. على سبيل المثال، إذا كنت تريد بث كائنات JSON، فيمكنك اختيار JSONEachRow، وسيُحلَّل كل صف على أنه كائن JS، أو ربما التنسيق الأكثر إحكامًا JSONCompactColumns، الذي سيجعل كل صف مصفوفةً مضغوطة من القيم. انظر أيضًا: بث الملفات.
إذا لم يتم استهلاك ResultSet أو التدفق الخاص به بالكامل، فسيُتلف بعد فترة عدم النشاط request_timeout.
مثال: (Node.js/Web) استعلام يُرجع مجموعة بيانات بتنسيق JSONEachRow، مع استهلاك التدفّق بالكامل وتحليل المحتويات على هيئة كائنات JavaScript. الشيفرة المصدرية.
مثال: (Node.js فقط) نتيجة استعلام متدفقة بتنسيق JSONEachRow باستخدام النهج التقليدي on('data'). ويمكن استخدامه بالتبادل مع صيغة for await const. الشيفرة المصدرية.
مثال: (Node.js فقط) نتيجة استعلام متدفقة بتنسيق CSV باستخدام الأسلوب التقليدي on('data'). ويمكن استخدامه بالتبادل مع بنية for await const. الشيفرة المصدرية
مثال: (Node.js فقط) نتيجة استعلام متدفقة على شكل كائنات JavaScript بتنسيق JSONEachRow، ويُتعامل معها باستخدام صياغة for await const. ويمكن استخدام ذلك بدلًا من الأسلوب التقليدي on('data'). الشيفرة المصدرية.
تستخدم صياغة for await const شيفرة أقل قليلًا من نهج on('data')، لكنها قد تؤثر سلبًا في الأداء. راجع هذه المشكلة في مستودع Node.js لمزيد من التفاصيل.
مثال: (للويب فقط) التكرار عبر ReadableStream من الكائنات.

طريقة insert

هذه هي الطريقة الأساسية لإدراج البيانات.
نوع الإرجاع مقتضب، لأننا لا نتوقع استرجاع أي بيانات من الخادم ونستهلك دفق الاستجابة فورًا. إذا جرى تمرير مصفوفة فارغة إلى الطريقة insert، فلن تُرسَل عبارة insert إلى الخادم؛ وبدلًا من ذلك، ستُعاد الطريقة فورًا بالقيمة { query_id: '...', executed: false }. وإذا لم يُمرَّر query_id ضمن معلمات الطريقة في هذه الحالة، فستكون قيمته في النتيجة سلسلة فارغة، لأن إرجاع معرّف UUID عشوائي يولّده العميل قد يكون مُربِكًا، إذ إن الاستعلام ذي query_id هذا لن يكون موجودًا في جدول system.query_log. إذا أُرسلت عبارة insert إلى الخادم، فستكون العلامة executed هي true.

طريقة insert والدفق في Node.js

يمكن أن تعمل هذه الطريقة إما مع Stream.Readable أو مع Array<T> عادي، وذلك بحسب تنسيق البيانات المحدد لطريقة insert. راجع أيضًا هذا القسم حول دفق الملفات. من المفترض استخدام await مع طريقة insert؛ ومع ذلك، يمكن تحديد دفق إدخال ثم انتظار عملية insert لاحقًا، عند اكتمال الدفق فقط (وسيؤدي ذلك أيضًا إلى اكتمال الوعد الخاص بـ insert). قد يكون هذا مفيدًا في بعض الحالات، مثل مستمعات الأحداث والسيناريوهات المشابهة، لكن معالجة الأخطاء قد تكون معقدة بسبب كثرة الحالات الطرفية في جهة العميل. بدلًا من ذلك، فكّر في استخدام عمليات insert غير المتزامنة كما هو موضح في هذا المثال.
إذا كانت لديك عبارة INSERT مخصصة يصعب تمثيلها باستخدام هذه الطريقة، ففكّر في استخدام طريقة command.يمكنك الاطلاع على كيفية استخدامها في مثالي INSERT INTO … VALUES أو INSERT INTO … SELECT.
انظر أيضًا: المعلمات الأساسية لجميع طرق العميل.
لا يضمن إلغاء طلب باستخدام abort_signal عدم حدوث إدراج للبيانات، إذ قد يكون الخادم قد استقبل بعض البيانات المتدفقة قبل الإلغاء.
مثال: (Node.js/Web) إدراج مصفوفة من القيم. الشيفرة المصدرية.
مثال: (Node.js فقط) إدراج دفق من ملف CSV. الشيفرة المصدرية. انظر أيضًا: بث الملفات.
مثال: استبعِد أعمدة معيّنة من عبارة insert. إذا كان لديك تعريف جدول كالتالي:
أدرِج عمودًا محددًا فقط:
استبعاد أعمدة معيّنة:
راجع الشيفرة المصدرية للاطلاع على مزيد من التفاصيل. مثال: الإدراج في قاعدة بيانات تختلف عن تلك المحددة في مثيل العميل. الشيفرة المصدرية.

قيود إصدار الويب

حاليًا، لا تعمل عمليات الإدراج في @clickhouse/client-web إلا مع التنسيقات Array<T> وJSON*. ولا يزال إدراج التدفقات غير مدعوم في إصدار الويب بسبب ضعف التوافق مع المتصفحات. وبناءً على ذلك، تبدو واجهة InsertParams في إصدار الويب مختلفة قليلًا عن إصدار Node.js، إذ تقتصر values على النوع ReadonlyArray<T> فقط:
هذا عرضة للتغيير مستقبلًا. انظر أيضًا: Base parameters for all client methods.

طريقة command

يمكن استخدامها مع العبارات التي لا تُرجع أي مخرجات، عندما لا تكون عبارة format قابلة للتطبيق، أو عندما لا تكون مهتمًا بالاستجابة على الإطلاق. ومن أمثلة هذه العبارات CREATE TABLE أو ALTER TABLE. يجب استخدام await معها. يتم إتلاف تدفق الاستجابة فورًا، ما يعني تحرير socket الأساسي.
انظر أيضًا: Base parameters for all client methods. مثال: (Node.js/Web) أنشئ جدولًا في ClickHouse Cloud. الشيفرة المصدرية.
مثال: (Node.js/Web) أنشئ جدولًا في مثيل ClickHouse ذاتي الاستضافة. الشيفرة المصدرية.
مثال: (Node.js/الويب) INSERT FROM SELECT
إن إلغاء طلب باستخدام abort_signal لا يضمن أن الخادم لم ينفّذ التعليمة.

طريقة Exec

إذا كان لديك استعلام مخصّص لا يندرج ضمن query/insert، وكانت النتيجة تهمّك، فيمكنك استخدام exec كبديل لـ command. تعيد exec دفقًا قابلاً للقراءة ويجب استهلاكه أو إغلاقه من جانب التطبيق.
انظر أيضًا: Base parameters for all client methods. يختلف نوع القيمة المعادة للدفق بين Node.js وإصدار الويب. Node.js:
الويب:

Ping

تُرجِع الطريقة ping المخصّصة للتحقق من حالة الاتصال القيمة true إذا أمكن الوصول إلى الخادم. إذا تعذّر الوصول إلى الخادم، فستتضمن النتيجة أيضًا الخطأ الأساسي.
قد تكون Ping أداة مفيدة للتحقق مما إذا كان الخادم متاحًا عند بدء تشغيل التطبيق، لا سيما مع ClickHouse Cloud، حيث قد يكون المثيل في وضع الخمول ويستيقظ بعد إجراء ping. في هذه الحالة، قد ترغب في إعادة المحاولة بضع مرات مع تأخير بين كل محاولة وأخرى. لاحظ أنه افتراضيًا، يستخدم إصدار Node.js نقطة النهاية /ping، بينما يستخدم إصدار الويب استعلام SELECT 1 لتحقيق نتيجة مماثلة، لأن نقطة النهاية /ping لا تدعم CORS. مثال: (Node.js/Web) إجراء ping بسيط على مثيل خادم ClickHouse. ملاحظة: في إصدار الويب، ستكون الأخطاء التي يتم التقاطها مختلفة. الشيفرة المصدرية.
مثال: إذا كنت تريد أيضًا التحقق من بيانات الاعتماد عند استدعاء الطريقة ping، أو تمرير معاملات إضافية مثل query_id، فيمكنك استخدامها كما يلي:
ستدعم الطريقة ping معظم معلمات الطريقة query القياسية - راجع تعريف النوع PingParamsWithSelectQuery.

Close (Node.js فقط)

يُغلق جميع الاتصالات المفتوحة ويُحرِّر الموارد. لا يُحدث أي تأثير في إصدار الويب.

تدفّق الملفات (Node.js فقط)

تتوفر عدة أمثلة على تدفّق الملفات باستخدام تنسيقات البيانات الشائعة (NDJSON وCSV وParquet) في مستودع العميل. يُفترض أن يكون تدفّق التنسيقات الأخرى إلى ملف مشابهًا لـ Parquet، وسيكون الاختلاف الوحيد في التنسيق المستخدم في استدعاء query (JSONEachRow وCSV وما إلى ذلك) واسم ملف الإخراج.

تنسيقات البيانات المدعومة

يتعامل العميل مع تنسيقات البيانات بصيغة JSON أو كنص. إذا حدّدت format كأحد التنسيقات التابعة لعائلة JSON (JSONEachRow وJSONCompactEachRow وما إلى ذلك)، فسيقوم العميل بتسلسل البيانات وإلغاء تسلسلها أثناء نقلها عبر الشبكة. تُرسل البيانات المقدَّمة بتنسيقات النص “الخام” (CSV وعائلتا TabSeparated وCustomSeparated) عبر الشبكة كما هي، من دون أي تحويلات إضافية.
قد يحدث التباس بين JSON كتنسيق عام وتنسيق ClickHouse JSON.يدعم العميل تدفّق كائنات JSON باستخدام تنسيقات مثل JSONEachRow (راجع نظرة عامة الجدول للاطلاع على التنسيقات الأخرى المناسبة للبث؛ وراجع أيضًا أمثلة select_streaming_ في مستودع العميل).المسألة فقط أن تنسيقات مثل ClickHouse JSON وبعض التنسيقات الأخرى تُمثَّل ككائن واحد في الاستجابة، ولذلك لا يمكن للعميل تدفّقها.
بالنسبة إلى Parquet، يُرجَّح أن تكون حالة الاستخدام الرئيسية لعمليات SELECT هي كتابة التدفق الناتج إلى ملف. راجع المثال في مستودع العميل. JSONEachRowWithProgress هو تنسيق مخصّص للإخراج فقط ويدعم الإبلاغ عن التقدم ضمن التدفق. راجع هذا المثال لمزيد من التفاصيل. تتوفر القائمة الكاملة لتنسيقات الإدخال والإخراج في ClickHouse هنا.

أنواع بيانات ClickHouse المدعومة

ينطبق نوع JS المرتبط على أي تنسيقات JSON*، باستثناء التنسيقات التي تمثل كل شيء كسلسلة نصية (مثل JSONStringEachRow)
القائمة الكاملة لتنسيقات ClickHouse المدعومة متاحة هنا. انظر أيضًا:

محاذير أنواع Date/Date32

نظرًا لأن العميل يُدرج القيم من دون أي تحويل إضافي للنوع، فلا يمكن إدراج الأعمدة من النوع Date/Date32 إلا كسلاسل نصية. مثال: أدرج قيمة من النوع Date. الشيفرة المصدرية
ومع ذلك، إذا كنت تستخدم أعمدة DateTime أو DateTime64، يمكنك استخدام كلٍّ من السلاسل النصية وكائنات JS Date. ويمكن تمرير كائنات JS Date إلى insert كما هي مع ضبط date_time_input_format على best_effort. راجع هذا المثال لمزيد من التفاصيل.

محاذير أنواع Decimal*

يمكن إدراج قيم Decimal باستخدام تنسيقات من عائلة JSON*. بافتراض أن لدينا جدولًا معرّفًا كما يلي:
يمكن إدراج القيم دون فقدان الدقة باستخدام التمثيل النصي:
ومع ذلك، عند الاستعلام عن البيانات بتنسيقات JSON*، سيُرجع ClickHouse قيم Decimal على شكل أرقام افتراضيًا، مما قد يؤدي إلى فقدان الدقة. لتجنّب ذلك، يمكنك تحويل قيم Decimal إلى سلسلة نصية في الاستعلام:
راجع هذا المثال لمزيد من التفاصيل.

الأنواع العددية الصحيحة: Int64, Int128, Int256, UInt64, UInt128, UInt256

على الرغم من أن الخادم يمكنه قبولها كأرقام، فإنها تُعاد كسلاسل نصية في تنسيقات الإخراج من عائلة JSON* لتجنب overflow للأعداد الصحيحة، لأن القيم القصوى لهذه الأنواع أكبر من Number.MAX_SAFE_INTEGER. ومع ذلك، يمكن تعديل هذا السلوك باستخدام إعداد output_format_json_quote_64bit_integers . مثال: اضبط تنسيق إخراج JSON للأرقام ذات 64 بت.

إعدادات ClickHouse

يمكن للعميل تعديل سلوك ClickHouse من خلال آلية الإعدادات. يمكن تعيين الإعدادات على مستوى مثيل العميل بحيث تُطبَّق على كل طلب يُرسَل إلى ClickHouse:
أو يمكن ضبط إعداد على مستوى الطلب:
يمكن العثور على ملف تعريف الأنواع الذي يضم جميع إعدادات ClickHouse المدعومة هنا.
تأكد من أن المستخدم الذي تُنفَّذ الاستعلامات نيابةً عنه لديه الصلاحيات الكافية لتغيير الإعدادات.

موضوعات متقدمة

الاستعلامات ذات المعلمات

يمكنك إنشاء استعلامٍ بمعلمات وتمرير قيَم إليها من تطبيق العميل. يتيح لك ذلك تجنب تنسيق الاستعلام بقيَم ديناميكية محددة على جهة العميل. نسّق الاستعلام كالمعتاد، ثم ضع القيَم التي تريد تمريرها من معلمات التطبيق إلى الاستعلام بين أقواس بالتنسيق التالي:
حيث:
  • name — معرّف العنصر النائب.
  • data_type - نوع البيانات لقيمة مَعلمة التطبيق.
مثال:: استعلام بمعلمات. الشيفرة المصدرية .
اطّلع على https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax لمزيد من التفاصيل.

الضغط

ملاحظة: ضغط الطلبات غير متاح حاليًا في إصدار الويب. أما ضغط الاستجابات فيعمل بشكل طبيعي. ويدعم إصدار Node.js الاثنين معًا. يمكن أن تستفيد تطبيقات البيانات التي تعمل مع مجموعات بيانات كبيرة عبر الشبكة من تفعيل الضغط. حاليًا، لا يتوفر الدعم إلا لـ GZIP باستخدام zlib.
معلمات الإعداد هي:
  • response: true يوجّه ClickHouse server لإرسال جسم الاستجابة مضغوطًا. القيمة الافتراضية: response: false
  • request: true يفعّل الضغط في جسم طلب العميل. القيمة الافتراضية: request: false

التسجيل (Node.js فقط)

يُعدّ التسجيل ميزة تجريبية وقد يتغير في المستقبل.
يقوم تنفيذ المُسجِّل الافتراضي بإخراج سجلات السجل إلى stdout عبر الطريقتين console.debug/info، وإلى stderr عبر الطريقتين console.warn/error. يمكنك تخصيص منطق التسجيل من خلال توفير LoggerClass، واختيار مستوى السجل المطلوب عبر المعامل level (القيمة الافتراضية هي WARN):
حاليًا، سيسجّل العميل الأحداث التالية:
  • TRACE - معلومات منخفضة المستوى عن دورة حياة مقابس Keep-Alive
  • DEBUG - معلومات الاستجابة (من دون رؤوس التفويض ومعلومات المضيف)
  • INFO - غير مستخدم في الغالب، ويطبع مستوى السجل الحالي عند تهيئة العميل
  • WARN - أخطاء غير فادحة؛ يُسجَّل طلب ping الفاشل كتحذير، لأن الخطأ الأساسي يكون مضمنًا في النتيجة المعادة
  • ERROR - أخطاء فادحة من الطرق query/insert/exec/command، مثل فشل الطلب
يمكنك العثور على تطبيق Logger الافتراضي هنا.

شهادات TLS ‏(Node.js فقط)

يوفّر عميل Node.js دعمًا اختياريًا لكلٍّ من TLS الأساسي (Certificate Authority فقط) وTLS المتبادل (Certificate Authority وشهادات العميل). مثال على تهيئة TLS الأساسية، بافتراض أن شهاداتك موجودة في المجلد certs وأن اسم ملف CA هو CA.pem:
مثال على تهيئة TLS المتبادل باستخدام شهادات العميل:
اطّلع على الأمثلة الكاملة لـ TLS الأساسي والمتبادل في المستودع.

إعداد Keep-Alive (Node.js فقط)

يُفعّل العميل Keep-Alive في وكيل HTTP الأساسي افتراضيًا، ما يعني إعادة استخدام المقابس المتصلة للطلبات اللاحقة، مع إرسال الترويسة Connection: keep-alive. وتبقى المقابس الخاملة ضمن مجموعة الاتصالات لمدة 2500 مللي ثانية افتراضيًا (راجع الملاحظات حول ضبط هذا الخيار). يُفترض أن تكون قيمة keep_alive.idle_socket_ttl أقل بفارق ملحوظ من إعدادات الخادم/موازن التحميل. والسبب الرئيسي هو أنه، نظرًا لأن HTTP/1.1 يسمح للخادم بإغلاق المقابس من دون إخطار العميل، فإذا أغلق الخادم أو موازن التحميل الاتصال قبل أن يغلقه العميل، فقد يحاول العميل إعادة استخدام مقبس مغلق، ما يؤدي إلى الخطأ socket hang up. إذا كنت تعدّل keep_alive.idle_socket_ttl، فضع في اعتبارك أنه يجب أن يظل متوافقًا دائمًا مع إعدادات Keep-Alive الخاصة بالخادم/موازن التحميل، وأن يكون أقل منها دائمًا، بما يضمن ألا يغلق الخادم الاتصال المفتوح أولًا.

ضبط idle_socket_ttl

يضبط العميل keep_alive.idle_socket_ttl على 2500 ملّي ثانية، إذ يمكن اعتبارها القيمة الافتراضية الأكثر أمانًا؛ وعلى جانب الخادم، قد يُضبط keep_alive_timeout على قيمة منخفضة تصل إلى 3 ثوانٍ في إصدارات ClickHouse الأقدم من 23.11 من دون أي تعديلات على config.xml.
إذا كنت راضيًا عن الأداء ولا تواجه أي مشكلات، فمن المستحسن عدم زيادة قيمة الإعداد keep_alive.idle_socket_ttl، لأن ذلك قد يؤدي إلى أخطاء محتملة من نوع “Socket hang-up”؛ كذلك، إذا كان تطبيقك يرسل الكثير من الاستعلامات ولم تكن هناك فترات توقف طويلة بينها، فمن المفترض أن تكون القيمة الافتراضية كافية، لأن المقابس لن تبقى في حالة خمول لمدة تكفي لذلك، وسيُبقيها العميل ضمن المجمّع.
يمكنك العثور على قيمة مهلة Keep-Alive الصحيحة في ترويسات استجابة الخادم بتشغيل الأمر التالي:
تحقق من قيم ترويستي Connection وKeep-Alive في الاستجابة. على سبيل المثال:
في هذه الحالة، تكون قيمة keep_alive_timeout 10 ثوانٍ، ويمكنك محاولة زيادة keep_alive.idle_socket_ttl إلى 9000 أو حتى 9500 مللي ثانية للإبقاء على المقابس الخاملة مفتوحة لفترة أطول قليلًا من الوضع الافتراضي. راقب أي أخطاء محتملة من نوع “Socket hang-up”، إذ تشير إلى أن الخادم يغلق الاتصالات قبل أن يغلقها العميل، وخفِّض القيمة حتى تختفي الأخطاء.

استكشاف الأخطاء وإصلاحها

إذا كنت تواجه أخطاء socket hang up حتى عند استخدام أحدث إصدار من العميل، فهناك الخيارات التالية لحل هذه المشكلة:
  • فعِّل السجلات بمستوى WARN على الأقل (وهو المستوى الافتراضي). يتيح ذلك التحقق مما إذا كان هناك دفق غير مستهلك أو دفق معلّق في شيفرة التطبيق؛ إذ ستسجّله طبقة النقل عند مستوى WARN، لأن ذلك قد يؤدي إلى إغلاق المقبس من جانب الخادم. يمكنك تفعيل التسجيل في إعدادات العميل كما يلي:
  • تأكد من أن الإعداد المطلوب مُطبَّق على مثيل العميل الصحيح. إذا كان لديك عدة مثيلات للعميل في تطبيقك، فتحقق مرة أخرى من أن المثيل الذي تستخدمه للاستعلامات لديه القيمة الصحيحة لـ keep_alive.idle_socket_ttl.
  • خفِّض إعداد keep_alive.idle_socket_ttl في إعدادات العميل بمقدار 500 مللي ثانية. في بعض الحالات، مثل ارتفاع كمون الشبكة بين العميل والخادم، قد يكون هذا مفيدًا لتجنّب الحالة التي يحصل فيها طلب صادر على مقبس على وشك أن يغلقه الخادم.
  • إذا كان هذا الخطأ يحدث أثناء الاستعلامات طويلة التشغيل من دون وجود بيانات داخلة أو خارجة (على سبيل المثال، INSERT FROM SELECT طويل التشغيل)، فقد يكون السبب موازن تحميل أو مكونات شبكة أخرى تغلق الاتصالات طويلة الأمد أو الطلبات طويلة التشغيل. يمكنك محاولة فرض وصول بعض البيانات أثناء الاستعلامات طويلة التشغيل باستخدام مجموعة إعدادات ClickHouse التالية:
    ومع ذلك، ضع في اعتبارك أن الحجم الإجمالي للترويسات المستلمة له حد أقصى قدره 16KB في الإصدارات الحديثة من Node.js؛ وبعد تلقّي عدد معيّن من ترويسات التقدم، وكان ذلك نحو 70-80 في اختباراتنا، سيجري إنشاء استثناء. ومن الممكن أيضًا استخدام نهج مختلف تمامًا، مع تجنّب وقت الانتظار في تنسيق النقل بالكامل؛ ويمكن فعل ذلك بالاستفادة من “الميزة” في واجهة HTTP التي تقضي بعدم إلغاء عمليات mutation عند فقدان الاتصال. راجع هذا المثال (الجزء 2) لمزيد من التفاصيل.
  • يمكن تعطيل ميزة Keep-Alive بالكامل. في هذه الحالة، سيضيف العميل أيضًا ترويسة Connection: close إلى كل طلب، ولن يعيد HTTP agent الأساسي استخدام الاتصالات. سيتم تجاهل إعداد keep_alive.idle_socket_ttl، إذ لن تكون هناك مقابس خاملة. سيؤدي هذا إلى كلفة إضافية، لأن اتصالًا جديدًا سيُنشأ لكل طلب.
  • استبعد المشكلات المحتملة في بقية مكدس الشبكة، بما في ذلك Node.js نفسه، عن طريق تشغيل اختبار بسيط من سطر الأوامر باستخدام مثيل ClickHouse نفسه ومسار الشبكة نفسه (أي من الجهاز نفسه أو من مقطع الشبكة نفسه، مثل pod في Kubernetes)، على سبيل المثال باستخدام curl:
    قد ترغب في تشغيله ضمن حلقة لعدة دقائق. إذا رأيت أخطاء مشابهة في curl، فمن المرجح أن المشكلة لا تتعلق بإعدادات العميل، بل بمكدس الشبكة أو إعدادات الخادم.
  • لاختبار الاتصال باستخدام وظائف Node.js الأساسية، يمكنك محاولة إنشاء HTTP request بسيطة إلى ClickHouse server باستخدام واجهة fetch API المدمجة:
  • في بعض الحالات، قد تضيف شيفرة التطبيق أو موائمات إطار العمل ping() استباقية قبل تنفيذ الاستعلام الفعلي، ما قد يؤدي إلى وضع ينجح فيه طلب ping()، لكن يفشل طلب الاستعلام اللاحق بخطأ “socket hang up” بسبب المشكلة الأساسية نفسها المرتبطة بالاتصالات الخاملة. إذا لاحظت هذا النمط في السجلات، فحاول التحقق مما إذا كان هناك خيار لتعطيل عمليات ping() الاستباقية في إطار العمل أو في شيفرة التطبيق. ومن المفترض أن يساعد ذلك أيضًا في تقليل احتمال التعرّض لتقييد المعدّل من أي من مكوّنات الشبكة الوسيطة.
  • تأكد من أن التطبيق نفسه يحصل على وقت CPU كافٍ، وأن الشبكة لا يقيّد موفّر الاستضافة معدلها. وقد تكون أيضًا وسائل المراقبة المختلفة، مثل مقاييس توقّف GC المؤقت، ومقاييس تأخر حلقة الأحداث، وما شابهها، مفيدة في استبعاد المشكلات المحتملة الناتجة عن شحّ الموارد.
  • جرّب فحص شيفرة التطبيق مع تفعيل قاعدة ESLint ‏no-floating-promises، إذ يساعد ذلك في تحديد الوعود غير المُعالجة التي قد تؤدي إلى تدفقات ومقابس معلّقة.

المستخدمون ذوو صلاحية القراءة فقط

عند استخدام العميل مع مستخدم readonly=1، لا يمكن تمكين ضغط الاستجابة، لأنه يتطلب الإعداد enable_http_compression. سيؤدي التكوين التالي إلى حدوث خطأ:
اطّلع على المثال الذي يسلّط الضوء بشكل أكبر على القيود المفروضة على المستخدم ذي readonly=1.

وكيل مع اسم مسار

إذا كان مثيل ClickHouse لديك خلف وكيل، وكانت هناك قيمة لاسم المسار ضمن عنوان URL، كما في المثال http://proxy:8123/clickhouse&#95;server، فحدِّد clickhouse_server كخيار الإعداد pathname (مع أو بدون شرطة مائلة في البداية)؛ وإلا، فإذا أُدرج مباشرةً في url فسيُعامل على أنه الخيار database. كما أن أسماء المسارات متعددة المقاطع مدعومة، مثل /my_proxy/db.

وكيل عكسي مع المصادقة

إذا كان لديك وكيل عكسي مع مصادقة أمام نشر ClickHouse لديك، فيمكنك استخدام الإعداد http_headers لتوفير الترويسات اللازمة هناك:

وكيل HTTP/HTTPS مخصص (تجريبي، Node.js فقط)

هذه ميزة تجريبية وقد تتغير مستقبلًا بشكل غير متوافق مع الإصدارات السابقة. ينبغي أن يكون التنفيذ الافتراضي والإعدادات التي يوفرها العميل كافية لمعظم حالات الاستخدام. لا تستخدم هذه الميزة إلا إذا كنت متأكدًا من حاجتك إليها.
افتراضيًا، سيُهيّئ العميل وكيل HTTP أو HTTPS الأساسي باستخدام الإعدادات المحددة في تهيئة العميل (مثل max_open_connections وkeep_alive.enabled وtls)، ليتولى إدارة الاتصالات مع خادم ClickHouse. بالإضافة إلى ذلك، إذا استُخدمت شهادات TLS، فسيُهيَّأ الوكيل الأساسي بالشهادات اللازمة، وستُفرض ترويسات مصادقة TLS الصحيحة. بعد الإصدار 1.2.0، أصبح من الممكن تزويد العميل بوكيل HTTP أو HTTPS مخصص ليحل محل الوكيل الأساسي الافتراضي. وقد يكون ذلك مفيدًا في حالات تهيئة الشبكة المعقدة. تنطبق الشروط التالية عند توفير وكيل مخصص:
  • لن يكون للخيارين max_open_connections وtls أي تأثير، وسيتجاهلهما العميل، لأنهما جزء من تهيئة الوكيل الأساسي.
  • سيقتصر keep_alive.enabled على تحديد القيمة الافتراضية لترويسة Connection (true -> Connection: keep-alive، false -> Connection: close).
  • مع أن إدارة مقابس keep-alive الخاملة ستستمر في العمل (لأنها لا ترتبط بالوكيل، بل بالمقبس نفسه)، فقد أصبح من الممكن الآن تعطيلها بالكامل بضبط قيمة keep_alive.idle_socket_ttl على 0.

أمثلة على استخدام وكيل مخصّص

استخدام وكيل HTTP أو HTTPS مخصّص من دون شهادات:
استخدام HTTPS Agent مخصّص مع إعداد TLS أساسي وشهادة CA:
استخدام HTTPS Agent مخصّص مع TLS المتبادل:
عند استخدام الشهادات و وكيل HTTPS مخصّص، يُرجَّح أن يلزم تعطيل ترويسة التفويض الافتراضية عبر الإعداد set_basic_auth_header (أُضيف في الإصدار 1.2.0)، لأنها تتعارض مع ترويسات TLS. ويجب توفير جميع ترويسات TLS يدويًا.

القيود المعروفة (Node.js/web)

  • لا توجد مُحوِّلات بيانات لمجموعات النتائج، لذا لا تُستخدم سوى الأنواع البدائية في اللغة. ومن المخطط إضافة بعض مُحوِّلات أنواع البيانات مع دعم RowBinary format.
  • توجد بعض الملاحظات المتعلقة بأنواع البيانات Decimal* وDate* / DateTime*.
  • عند استخدام تنسيقات عائلة JSON*، تُمثَّل الأرقام الأكبر من Int32 كسلاسل نصية، لأن القيم القصوى لأنواع Int64+ أكبر من Number.MAX_SAFE_INTEGER. راجع قسم Integral types لمزيد من التفاصيل.

القيود المعروفة (الويب)

  • يعمل التدفّق مع استعلامات select، لكنه معطّل لعمليات insert (وعلى مستوى النوع أيضًا).
  • ضغط الطلبات معطّل، ويتم تجاهل الإعدادات. أما ضغط الاستجابة فيعمل.
  • لا يتوفر دعم للتسجيل حتى الآن.

نصائح لتحسين الأداء

  • لتقليل استهلاك ذاكرة التطبيق، يُنصح باستخدام التدفقات في عمليات الإدراج الكبيرة (مثلًا من الملفات) واستعلامات SELECT عند الحاجة. وبالنسبة إلى مستمعي الأحداث وحالات الاستخدام المشابهة، قد تكون الإدراجات غير المتزامنة خيارًا جيدًا آخر، إذ تتيح تقليل التجميع على جهة العميل أو حتى الاستغناء عنه تمامًا. تتوفر أمثلة على الإدراج غير المتزامن في مستودع العميل، حيث تأتي أسماء الملفات بالبادئة async_insert_.
  • لا يفعّل العميل ضغط الطلبات أو الاستجابات افتراضيًا. ومع ذلك، عند تنفيذ استعلامات SELECT أو إدراج مجموعات بيانات كبيرة، يمكنك التفكير في تفعيله عبر ClickHouseClientConfigOptions.compression (إما لـ request فقط أو response فقط أو لكليهما).
  • يفرض الضغط أثرًا ملحوظًا على الأداء. فتفعيله لـ request أو response سيؤثر سلبًا في سرعة استعلامات SELECT أو عمليات الإدراج، على التوالي، لكنه سيقلل حجم حركة مرور الشبكة التي ينقلها التطبيق.

تواصل معنا

إذا كانت لديك أي أسئلة أو احتجت إلى مساعدة، فلا تتردد في التواصل معنا على Community Slack (قناة #clickhouse-js) أو عبر GitHub issues.
آخر تعديل في ٢٣ يوليو ٢٠٢٦