الانتقال إلى المحتوى الرئيسي

إدراج البيانات في ClickHouse مقارنةً بقواعد بيانات OLTP

باعتبار ClickHouse قاعدة بيانات OLAP (Online Analytical Processing)، فهو مُحسَّن لتحقيق أداء عالٍ وقابلية توسّع كبيرة، بما يتيح نظريًا إدراج ملايين الصفوف في الثانية. ويتحقق ذلك من خلال الجمع بين معمارية عالية التوازي وضغط فعّال موجَّه للأعمدة، لكن مقابل بعض التنازلات على مستوى الاتساق الفوري. وبشكل أدق، جرى تحسين ClickHouse لعمليات الإلحاق فقط، ولا يوفّر إلا ضمانات الاتساق النهائي. في المقابل، جرى تحسين قواعد بيانات OLTP مثل Postgres خصيصًا لعمليات الإدراج المعاملاتية مع امتثال كامل لمبادئ ACID، بما يضمن اتساقًا قويًا وموثوقية عالية. ويستخدم PostgreSQL آلية MVCC ‏(Multi-Version Concurrency Control) للتعامل مع المعاملات المتزامنة، وهو ما يتطلب الاحتفاظ بعدة إصدارات من البيانات. وقد تتعامل هذه المعاملات مع عدد صغير من الصفوف في كل مرة، مع تحمّل كلفة إضافية ملحوظة بسبب ضمانات الموثوقية التي تحدّ من أداء الإدراج. ولتحقيق أداء إدراج مرتفع مع الحفاظ على ضمانات اتساق قوية، ينبغي الالتزام بالقواعد البسيطة الموضحة أدناه عند إدراج البيانات في ClickHouse. وسيساعدك اتباع هذه القواعد على تجنّب المشكلات التي يواجهها المستخدمون عادةً عند استخدام ClickHouse لأول مرة، ومحاولة تطبيق استراتيجية إدراج تناسب قواعد بيانات OLTP.

أفضل الممارسات لعمليات الإدراج

الإدراج على دفعات كبيرة

افتراضيًا، تؤدي كل عملية إدراج تُرسل إلى ClickHouse إلى أن ينشئ ClickHouse فورًا جزءًا تخزينيًا يحتوي على بيانات عملية إدراج، إلى جانب بيانات وصفية أخرى يجب تخزينها. لذلك، فإن إرسال عدد أقل من عمليات إدراج، تحتوي كل واحدة منها على قدر أكبر من البيانات، مقارنةً بإرسال عدد أكبر من عمليات إدراج، تحتوي كل واحدة منها على قدر أقل من البيانات، يقلل عدد عمليات الكتابة المطلوبة. وبوجه عام، نوصي بإدراج البيانات في دفعات كبيرة نسبيًا لا تقل عن 1,000 صف في المرة الواحدة، ومن المثالي أن تتراوح بين 10,000 و100,000 صف. (مزيد من التفاصيل هنا). إذا لم تكن الدفعات الكبيرة ممكنة، فاستخدم عمليات الإدراج غير المتزامنة الموضحة أدناه.

احرص على اتساق الدُفعات لإعادة المحاولة المتماثلة الأثر

بشكل افتراضي، تكون عمليات الإدراج في ClickHouse متزامنة ومتماثلة الأثر (أي إن تنفيذ عملية الإدراج نفسها عدة مرات يعطي النتيجة نفسها كما لو نُفذت مرة واحدة فقط). وبالنسبة إلى الجداول من عائلة محركات MergeTree، يَعمل ClickHouse، افتراضيًا، على إزالة التكرار من عمليات الإدراج تلقائيًا. وهذا يعني أن عمليات الإدراج تظل مرنة في الحالات التالية:
    1. إذا كانت هناك مشكلات في العقدة التي تستقبل البيانات، فستنتهي مهلة استعلام الإدراج (أو سيُرجع خطأً أكثر تحديدًا) ولن يتلقى المُرسِل أي إقرار.
    1. إذا كانت العقدة قد كتبت البيانات ولكن تعذّر إعادة الإقرار إلى مُرسِل الاستعلام بسبب انقطاع الشبكة، فسيتلقى المُرسِل إما انتهاء مهلة أو خطأً في الشبكة.
ومن منظور العميل، قد يصعب التمييز بين الحالتين (i) و(ii). ومع ذلك، في كلتا الحالتين، يمكن ببساطة إعادة محاولة عملية الإدراج التي لم يصل إقرار بها فورًا. وطالما أن استعلام الإدراج المُعاد يحتوي على البيانات نفسها وبالترتيب نفسه، فسيتجاهل ClickHouse تلقائيًا عملية الإدراج المُعادة إذا كانت عملية الإدراج الأصلية (التي لم يصل إقرار بها) قد نجحت.

الإدراج في جدول MergeTree أو جدول موزّع

نوصي بالإدراج مباشرةً في جدول MergeTree (أو جدول Replicated)، مع موازنة الطلبات عبر مجموعة من العقد إذا كانت البيانات موزعة على عدة شظايا، وضبط internal_replication=true. يترك هذا لـ ClickHouse مهمة نسخ البيانات إلى أي replica متاحة ضمن الشظايا، ويضمن أن تصبح البيانات متسقة في نهاية المطاف. إذا كانت موازنة الحمل من جهة العميل غير عملية، فيمكنك الإدراج عبر جدول موزّع، والذي سيتولى بعد ذلك توزيع عمليات الكتابة عبر العقد. ومرة أخرى، يُنصح بضبط internal_replication=true. ومع ذلك، تجدر الإشارة إلى أن هذا النهج أقل كفاءةً قليلًا، لأن عمليات الكتابة يجب أن تتم محليًا على العقدة التي تحتوي على الجدول الموزّع ثم تُرسل إلى الشظايا.

استخدم عمليات الإدراج غير المتزامن للدفعات الصغيرة

هناك سيناريوهات لا يكون فيها التجميع على جهة العميل عمليًا، مثل حالات استخدام observability التي تتضمن مئات أو آلاف الوكلاء المخصصين لمهام محددة ويرسلون السجلات والمقاييس وآثار التتبع وما إلى ذلك. في هذا السيناريو، يكون نقل هذه البيانات في الوقت الفعلي أمرًا بالغ الأهمية لاكتشاف المشكلات والحالات الشاذة بأسرع ما يمكن. علاوة على ذلك، هناك خطر حدوث ارتفاعات مفاجئة في الأحداث داخل الأنظمة الخاضعة للمراقبة، ما قد يؤدي إلى زيادات كبيرة في الذاكرة ومشكلات مرتبطة بها عند محاولة تخزين بيانات observability مؤقتًا على جهة العميل. إذا تعذر إدراج دفعات كبيرة، فيمكنك إسناد التجميع إلى ClickHouse باستخدام عمليات الإدراج غير المتزامن. مع عمليات الإدراج غير المتزامن، تُدرج البيانات أولًا في مخزن مؤقت، ثم تُكتب لاحقًا إلى مساحة تخزين قاعدة البيانات عبر 3 خطوات، كما يوضح المخطط أدناه: عند تمكين عمليات الإدراج غير المتزامن، يقوم ClickHouse بما يلي: (1) يستقبل استعلام الإدراج بشكل غير متزامن. (2) يكتب بيانات الاستعلام أولًا إلى مخزن مؤقت في الذاكرة. (3) يرتب البيانات ويكتبها كجزء في مساحة تخزين قاعدة البيانات، فقط عند تنفيذ عملية التفريغ التالية للمخزن المؤقت. قبل تفريغ المخزن المؤقت، يمكن تجميع بيانات استعلامات الإدراج غير المتزامنة الأخرى من العميل نفسه أو من عملاء آخرين داخل المخزن المؤقت. وقد يحتوي الجزء الناتج عن تفريغ المخزن المؤقت على بيانات من عدة استعلامات إدراج غير متزامنة. وعمومًا، تنقل هذه الآلية عملية تجميع البيانات من جهة العميل إلى جهة الخادم (ClickHouse instance).
لاحظ أن البيانات لا تكون قابلة للبحث عبر الاستعلامات قبل تفريغها إلى مساحة تخزين قاعدة البيانات، وأن تفريغ المخزن المؤقت قابل للتهيئة.يمكن العثور على التفاصيل الكاملة حول تهيئة عمليات الإدراج غير المتزامن هنا، مع شرح متعمق هنا.

استخدم عملاء ClickHouse الرسميين

يوفّر ClickHouse عملاءً لأكثر لغات البرمجة شيوعًا. وقد جرى تحسين هذه العملاء لضمان تنفيذ عمليات الإدراج بشكل صحيح، كما أنها تدعم الإدراجات غير المتزامنة دعمًا أصيلًا، إما مباشرةً كما في Go client، أو بصورة غير مباشرة عند تمكينها في إعدادات مستوى الاستعلام أو المستخدم أو الاتصال. راجع Clients and Drivers للاطلاع على القائمة الكاملة لعملاء ClickHouse وبرامج التشغيل المتاحة.

فضّل تنسيق Native

يدعم ClickHouse العديد من تنسيقات الإدخال عند تنفيذ عمليات الإدراج (وكذلك الاستعلامات). ويُعد هذا اختلافًا جوهريًا عن قواعد بيانات OLTP، كما أنه يسهّل كثيرًا تحميل البيانات من المصادر الخارجية، خاصةً عند اقترانه بـ دوال الجداول وإمكانية تحميل البيانات من الملفات الموجودة على القرص. وتُعد هذه التنسيقات مثاليةً لعمليات تحميل البيانات المخصصة ولمهام هندسة البيانات. بالنسبة إلى التطبيقات التي تسعى إلى تحقيق أفضل أداء ممكن لعمليات الإدراج، ينبغي استخدام تنسيق Native عند الإدراج. ويدعمه معظم العملاء (مثل Go وبايثون)، ويضمن ألا يضطر الخادم إلا إلى قدرٍ ضئيل من العمل، لأن هذا التنسيق موجّه للأعمدة بالفعل. وبذلك تنتقل مسؤولية تحويل البيانات إلى تنسيق موجّه للأعمدة إلى جهة العميل. وهذا مهم لتحجيم عمليات الإدراج بكفاءة. وبدلاً من ذلك، يمكنك استخدام RowBinary format (كما في Java client) إذا كنت تفضّل تنسيقًا صفّيًا — إذ يكون عادةً أسهل في الكتابة من تنسيق Native. وهذا الخيار أكثر كفاءة، من حيث الضغط وعبء الشبكة والمعالجة على الخادم، مقارنةً بتنسيقات الصفوف البديلة مثل JSON. ويمكن النظر في تنسيق JSONEachRow إذا كان معدل كتابة البيانات لديك منخفضًا وتريد التكامل بسرعة. لكن ينبغي الانتباه إلى أن هذا التنسيق يفرض عبئًا على CPU في ClickHouse بسبب التحليل.

استخدام واجهة HTTP

على عكس كثير من قواعد البيانات التقليدية، يدعم ClickHouse واجهة HTTP. يمكنك استخدامها لكلٍّ من إدراج البيانات والاستعلام عنها، بأيٍّ من التنسيقات المذكورة أعلاه. وغالبًا ما يكون هذا الخيار أفضل من البروتوكول الأصلي لـ ClickHouse، لأنه يسهّل تحويل حركة المرور باستخدام موازنات التحميل. ونتوقع وجود فروق طفيفة في أداء الإدراج مع البروتوكول الأصلي، لأنه يضيف عبئًا إضافيًا أقل قليلًا. تستخدم البرامج العميلة الحالية أحد هذين البروتوكولين (وفي بعض الحالات كليهما، مثل Go client). كما يتيح البروتوكول الأصلي تتبّع تقدّم الاستعلام بسهولة. راجع واجهة HTTP لمزيد من التفاصيل.

مثال بسيط

يمكنك استخدام الأمر المألوف INSERT INTO TABLE مع ClickHouse. لِنُدرِج بعض البيانات في الجدول الذي أنشأناه في دليل البدء السريع “إنشاء الجداول في ClickHouse”.
INSERT INTO helloworld.my_first_table (user_id, message, timestamp, metric) VALUES
    (101, 'Hello, ClickHouse!',                                 now(),       -1.0    ),
    (102, 'Insert a lot of rows per batch',                     yesterday(), 1.41421 ),
    (102, 'Sort your data based on your commonly-used queries', today(),     2.718   ),
    (101, 'Granules are the smallest chunks of data read',      now() + 5,   3.14159 )
للتحقق من نجاح ذلك، سننفّذ استعلام SELECT التالي:
SELECT * FROM helloworld.my_first_table
ويُرجع:
user_id message                                             timestamp           metric
101         Hello, ClickHouse!                                  2024-11-13 20:01:22     -1
101         Granules are the smallest chunks of data read           2024-11-13 20:01:27 3.14159
102         Insert a lot of rows per batch                          2024-11-12 00:00:00 1.41421
102         Sort your data based on your commonly-used queries  2024-11-13 00:00:00     2.718

تحميل البيانات من Postgres

لتحميل البيانات من Postgres، يمكنك استخدام:
  • ClickPipes، وهي أداة ETL مصممة خصيصًا لنسخ بيانات قواعد PostgreSQL. وهي متاحة في كلٍّ من:
  • محرك جداول PostgreSQL لقراءة البيانات مباشرةً كما هو موضح في الأمثلة السابقة. ويكون هذا مناسبًا عادةً إذا كان النسخ على دفعات استنادًا إلى قيمة watermark معروفة، مثل الطابع الزمني، كافيًا، أو إذا كانت هذه عملية ترحيل لمرة واحدة. يمكن لهذا النهج التوسع إلى عشرات الملايين من الصفوف. وينبغي للمستخدمين الذين يعتزمون ترحيل مجموعات بيانات أكبر التفكير في استخدام عدة طلبات، يتعامل كلٌّ منها مع جزء من البيانات. ويمكن استخدام جداول مرحلية لكل جزء قبل نقل أقسامه إلى جدول نهائي. وهذا يتيح إعادة محاولة الطلبات الفاشلة. لمزيد من التفاصيل حول استراتيجية التحميل المجمّع هذه، راجع هنا.
  • يمكن تصدير البيانات من PostgreSQL بتنسيق CSV. وبعد ذلك يمكن إدراجها في ClickHouse إما من ملفات محلية أو عبر التخزين الكائني باستخدام دوال الجداول.
هل تحتاج إلى مساعدة في إدراج مجموعات بيانات كبيرة؟إذا كنت بحاجة إلى مساعدة في إدراج مجموعات بيانات كبيرة أو واجهت أي أخطاء عند استيراد البيانات إلى ClickHouse Cloud، فيُرجى التواصل معنا على support@clickhouse.com وسنساعدك.

إدراج البيانات من سطر الأوامر

المتطلبات المسبقة
  • قمت بتثبيت ClickHouse
  • clickhouse-server قيد التشغيل
  • لديك إمكانية الوصول إلى طرفية تتوفر فيها الأدوات wget و zcat و curl
في هذا المثال، سترى كيفية إدراج ملف CSV في ClickHouse من سطر الأوامر باستخدام clickhouse-client في الوضع الدفعي. لمزيد من المعلومات والأمثلة حول إدراج البيانات عبر سطر الأوامر باستخدام clickhouse-client في الوضع الدفعي، راجع “Batch mode”. سنستخدم Hacker News dataset في هذا المثال، والتي تحتوي على 28 مليون صف من بيانات Hacker News.
1

تنزيل ملف CSV

شغّل الأمر التالي لتنزيل نسخة CSV من مجموعة البيانات من حاوية S3 العامة الخاصة بنا:
wget https://datasets-documentation.s3.eu-west-3.amazonaws.com/hackernews/hacknernews.csv.gz
يبلغ حجم هذا الملف المضغوط 4.6 جيجابايت، ويحتوي على 28 مليون صف، ومن المفترض أن يستغرق تنزيله من 5 إلى 10 دقائق.
2

إنشاء الجدول

مع تشغيل clickhouse-server، يمكنك إنشاء جدول فارغ بالمخطط التالي مباشرةً من سطر الأوامر باستخدام clickhouse-client في الوضع الدفعي:
clickhouse-client <<'_EOF'
CREATE TABLE hackernews(
    `id` UInt32,
    `deleted` UInt8,
    `type` Enum('story' = 1, 'comment' = 2, 'poll' = 3, 'pollopt' = 4, 'job' = 5),
    `by` LowCardinality(String),
    `time` DateTime,
    `text` String,
    `dead` UInt8,
    `parent` UInt32,
    `poll` UInt32,
    `kids` Array(UInt32),
    `url` String,
    `score` Int32,
    `title` String,
    `parts` Array(UInt32),
    `descendants` Int32
)
ENGINE = MergeTree
ORDER BY id
_EOF
إذا لم تظهر أي أخطاء، فهذا يعني أنه تم إنشاء الجدول بنجاح. في الأمر أعلاه، استُخدمت علامات الاقتباس المفردة حول محدد Heredoc (_EOF) لمنع أي استيفاء. ومن دون علامات الاقتباس المفردة، سيكون من الضروري إجراء إفلات لأحرف backticks المحيطة بأسماء الأعمدة.
3

إدراج البيانات من سطر الأوامر

بعد ذلك، شغّل الأمر أدناه لإدراج البيانات من الملف الذي نزّلته سابقًا في جدولك:
zcat < hacknernews.csv.gz | ./clickhouse client --query "INSERT INTO hackernews FORMAT CSV"
ونظرًا لأن بياناتنا مضغوطة، نحتاج أولًا إلى فك ضغط الملف باستخدام أداة مثل gzip أو zcat أو ما شابه ذلك، ثم تمرير البيانات بعد فك ضغطها إلى clickhouse-client مع تعليمة INSERT المناسبة وFORMAT.
عند إدراج البيانات باستخدام clickhouse-client في الوضع التفاعلي، يمكنك ترك ClickHouse يتولى فك الضغط نيابةً عنك عند الإدراج باستخدام العبارة COMPRESSION. ويمكن لـ ClickHouse اكتشاف نوع الضغط تلقائيًا من امتداد الملف، كما يمكنك أيضًا تحديده صراحةً.وسيبدو استعلام الإدراج حينها كما يلي:
clickhouse-client --query "INSERT INTO hackernews FROM INFILE 'hacknernews.csv.gz' COMPRESSION 'gzip' FORMAT CSV;"
عند اكتمال إدراج البيانات، يمكنك تشغيل الأمر التالي لمعرفة عدد الصفوف في جدول hackernews:
clickhouse-client --query "SELECT formatReadableQuantity(count(*)) FROM hackernews"
28.74 million
4

إدراج البيانات عبر سطر الأوامر باستخدام curl

في الخطوات السابقة، قمت أولًا بتنزيل ملف CSV إلى جهازك المحلي باستخدام wget. ومن الممكن أيضًا إدراج البيانات مباشرةً من URL البعيد باستخدام أمر واحد.شغّل الأمر التالي لتفريغ بيانات جدول hackernews حتى تتمكن من إدراجها مرة أخرى من دون الخطوة الوسيطة الخاصة بتنزيلها إلى جهازك المحلي:
clickhouse-client --query "TRUNCATE hackernews"
الآن شغّل:
curl https://datasets-documentation.s3.eu-west-3.amazonaws.com/hackernews/hacknernews.csv.gz | zcat | clickhouse-client --query "INSERT INTO hackernews FORMAT CSV"
يمكنك الآن تشغيل الأمر نفسه كما في السابق للتحقق من أن البيانات أُدرجت مرة أخرى:
clickhouse-client --query "SELECT formatReadableQuantity(count(*)) FROM hackernews"
28.74 million
آخر تعديل في ٢٥ يونيو ٢٠٢٦