الانتقال إلى المحتوى الرئيسي
تُعد ملفات القيم المفصولة بعلامات جدولة، أو TSV، شائعة، وقد تتضمن عناوين الحقول في السطر الأول من الملف. يمكن لـ ClickHouse إدخال ملفات TSV، كما يمكنه أيضًا الاستعلام عنها دون إدخالها. يغطي هذا الدليل كلتا الحالتين. وإذا كنت بحاجة إلى الاستعلام عن ملفات CSV أو إدخالها، فستنجح الأساليب نفسها؛ ما عليك سوى استبدال TSV بـ CSV في وسائط التنسيق. أثناء اتباع هذا الدليل، ستقوم بما يلي:
  • الاستكشاف: الاستعلام عن بنية ملف TSV ومحتواه.
  • تحديد مخطط ClickHouse المستهدف: اختيار أنواع البيانات المناسبة وربط البيانات الحالية بهذه الأنواع.
  • إنشاء جدول ClickHouse.
  • المعالجة المسبقة للبيانات وبثّها إلى ClickHouse.
  • تشغيل بعض الاستعلامات على ClickHouse.
تأتي مجموعة البيانات المستخدمة في هذا الدليل من فريق NYC Open Data، وتتضمن بيانات عن “جميع جرائم الجنايات والجنح والمخالفات الصالحة المُبلّغ عنها إلى إدارة شرطة مدينة نيويورك (NYPD)”. وعند كتابة هذا الدليل، كان حجم ملف البيانات 166 ميغابايت، لكنه يُحدَّث بانتظام. المصدر: data.cityofnewyork.us شروط الاستخدام: https://www1.nyc.gov/home/terms-of-use.page

المتطلبات الأساسية

ملاحظة حول الأوامر الموضَّحة في هذا الدليل

يوجد نوعان من الأوامر في هذا الدليل:
  • بعض الأوامر تستعلم من ملفات TSV، وتُشغَّل من موجّه الأوامر.
  • أما بقية الأوامر فتستعلم من ClickHouse، وتُشغَّل في clickhouse-client أو في واجهة Play UI.
تفترض الأمثلة في هذا الدليل أنك حفظت ملف TSV في ${HOME}/NYPD_Complaint_Data_Current__Year_To_Date_.tsv، لذا يُرجى تعديل الأوامر عند الحاجة.

تعرّف على ملف TSV

قبل البدء في العمل مع قاعدة بيانات ClickHouse، اطّلع على البيانات.

اطّلع على الحقول في ملف TSV المصدر

هذا مثال على أمر للاستعلام عن ملف TSV، ولكن لا تُشغِّله بعد.
Query
مثال على الاستجابة
في معظم الأحيان، سيُبيّن لك الأمر أعلاه أي الحقول في بيانات الإدخال رقمية، وأيها سلاسل نصية، وأيها tuples. لكن هذا لا يحدث دائمًا. ولأن ClickHouse يُستخدم عادةً مع مجموعات بيانات تحتوي على مليارات السجلات، يوجد حد افتراضي لعدد الصفوف التي تُفحص (100 صف) من أجل استنتاج المخطط، وذلك لتجنّب تحليل مليارات الصفوف لاستنتاج المخطط. قد لا تتطابق الاستجابة أدناه مع ما تراه لديك، لأن مجموعة البيانات تُحدَّث عدة مرات كل عام. وبالاطلاع على قاموس البيانات، يمكنك أن ترى أن CMPLNT_NUM محدد كنص، وليس كقيمة رقمية. ومن خلال تجاوز القيمة الافتراضية البالغة 100 صف للاستدلال باستخدام الإعداد SETTINGS input_format_max_rows_to_read_for_schema_inference=2000 يمكنك الحصول على فكرة أدق عن المحتوى.ملاحظة: اعتبارًا من الإصدار 22.5، أصبحت القيمة الافتراضية الآن 25,000 صف لاستنتاج المخطط، لذا لا تغيّر هذا الإعداد إلا إذا كنت تستخدم إصدارًا أقدم أو إذا كنت بحاجة إلى أخذ عينة تتجاوز 25,000 صف.
نفّذ هذا الأمر في موجّه الأوامر. ستستخدم clickhouse-local لإجراء استعلام على البيانات الموجودة في ملف TSV الذي نزّلته.
Query
Response
عند هذه المرحلة، ينبغي التحقق من أن الأعمدة في ملف TSV تطابق الأسماء والأنواع المحددة في قسم الأعمدة في مجموعة البيانات هذه ضمن صفحة ويب مجموعة البيانات. أنواع البيانات هنا ليست دقيقة جدًا؛ إذ إن جميع الحقول الرقمية معيّنة إلى Nullable(Float64)، وجميع الحقول الأخرى هي Nullable(String). وعند إنشاء جدول ClickHouse لتخزين البيانات، يمكنك تحديد أنواع أكثر ملاءمة وأفضل أداءً.

حدِّد المخطط المناسب

لتحديد الأنواع التي ينبغي استخدامها للحقول، لا بد من معرفة طبيعة البيانات. على سبيل المثال، الحقل JURISDICTION_CODE ذو قيمة رقمية: هل ينبغي أن يكون UInt8، أم Enum، أم أن Float64 هو الأنسب؟
Query
Response
تُظهر استجابة query أن JURISDICTION_CODE مناسب جدًا لـ UInt8. وبالمثل، انظر إلى بعض حقول String وتحقق مما إذا كانت أنسب لأن تكون من نوع DateTime أو LowCardinality(String). على سبيل المثال، يُوصَف الحقل PARKS_NM بأنه “اسم حديقة أو ساحة لعب أو مساحة خضراء في مدينة نيويورك مرتبطة بالواقعة، إن وُجدت (ولا تشمل حدائق الولاية)”. وقد تكون أسماء الحدائق في مدينة نيويورك مرشحًا جيدًا لـ LowCardinality(String):
Query
Response
ألقِ نظرة على بعض أسماء الحدائق:
Query
Response
تتضمن مجموعة البيانات المستخدمة وقت كتابة هذا النص بضع مئات فقط من المتنزهات وملاعب الأطفال المختلفة في العمود PARK_NM. وهذا عدد قليل وفقًا لتوصية LowCardinality بأن يبقى عدد السلاسل النصية المميزة في الحقل LowCardinality(String) دون 10,000.

حقول DateTime

استنادًا إلى قسم الأعمدة في مجموعة البيانات هذه في صفحة ويب مجموعة البيانات، توجد حقول للتاريخ والوقت تمثل بداية الحدث المُبلّغ عنه ونهايته. ويعطي النظر إلى القيمتين الدنيا والعليا للحقلين CMPLNT_FR_DT وCMPLT_TO_DT فكرة عمّا إذا كانت هذه الحقول تُملأ دائمًا أم لا:
Query
Response
Query
Response
Query
Response
Query
Response

ضع خطة

استنادًا إلى الاستقصاء أعلاه:
  • يجب إجراء cast لـ JURISDICTION_CODE إلى UInt8.
  • يجب إجراء cast لـ PARKS_NM إلى LowCardinality(String)
  • يتم دائمًا ملء CMPLNT_FR_DT و CMPLNT_FR_TM (وربما بوقت افتراضي هو 00:00:00)
  • قد يكون CMPLNT_TO_DT و CMPLNT_TO_TM فارغين
  • تُخزَّن التواريخ والأوقات في حقول منفصلة في المصدر
  • التواريخ بالتنسيق mm/dd/yyyy
  • الأوقات بالتنسيق hh:mm:ss
  • يمكن دمج التواريخ والأوقات في أنواع DateTime
  • توجد بعض التواريخ السابقة لـ 1 يناير 1970، ما يعني أننا بحاجة إلى DateTime ‏64 بت
هناك تغييرات أخرى كثيرة يجب إجراؤها على الأنواع، ويمكن تحديدها كلها باتباع خطوات الاستقصاء نفسها. انظر إلى عدد السلاسل النصية المميزة في الحقل، وإلى الحدين الأدنى والأقصى للقيم العددية، ثم اتخذ قراراتك. يحتوي مخطط الجدول الوارد لاحقًا في الدليل على كثير من السلاسل النصية منخفضة الكاردينالية وحقول الأعداد الصحيحة غير الموقعة، وعدد قليل جدًا من القيم العددية ذات الفاصلة العائمة.

دمج حقلي التاريخ والوقت

لدمج حقلي التاريخ والوقت CMPLNT_FR_DT وCMPLNT_FR_TM في قيمة String واحدة يمكن تحويلها إلى DateTime، حدِّد الحقلين مع ربطهما بعامل الدمج: CMPLNT_FR_DT || ' ' || CMPLNT_FR_TM. ويُتعامل مع الحقلين CMPLNT_TO_DT وCMPLNT_TO_TM بالطريقة نفسها.
Query
Response

حوِّل String الخاص بالتاريخ والوقت إلى النوع DateTime64

اكتشفنا سابقًا في هذا الدليل أن هناك تواريخ في ملف TSV تسبق 1 يناير 1970، ما يعني أننا بحاجة إلى نوع DateTime64 لهذه التواريخ. كما يجب أيضًا تحويل التواريخ من التنسيق MM/DD/YYYY إلى التنسيق YYYY/MM/DD. ويمكن تنفيذ الأمرين معًا باستخدام parseDateTime64BestEffort().
Query
يحتوي السطران 2 و3 أعلاه على ناتج الدمج من الخطوة السابقة، ويحوّل السطران 4 و5 أعلاه السلاسل النصية إلى DateTime64. ونظرًا لأن وقت انتهاء الشكوى ليس مضمونًا وجوده، يُستخدم parseDateTime64BestEffortOrNull.
Response
التواريخ المعروضة أعلاه على أنها 1925 ناتجة عن أخطاء في البيانات. توجد عدة سجلات في البيانات الأصلية تحمل تواريخ في السنوات 1019 - 1022، بينما يُفترض أن تكون 2019 - 2022. ويجري تخزينها على أنها 1 يناير 1925، لأنه أقدم تاريخ يدعمه DateTime بسعة 64 بت.

إنشاء جدول

تنعكس القرارات المتخذة أعلاه بشأن أنواع البيانات المستخدمة للأعمدة في مخطط الجدول أدناه. نحتاج أيضًا إلى تحديد ORDER BY وPRIMARY KEY المستخدمين في الجدول. يجب تحديد واحد على الأقل من ORDER BY أو PRIMARY KEY. فيما يلي بعض الإرشادات لتحديد الأعمدة التي ينبغي تضمينها في ORDER BY، وستجد مزيدًا من المعلومات في قسم الخطوات التالية في نهاية هذا المستند.

عبارتا ORDER BY وPRIMARY KEY

  • يجب أن يتضمن الـ tuple الخاص بـ ORDER BY الحقولَ المستخدمة في عوامل تصفية الاستعلام
  • لتحقيق أقصى ضغط على القرص، يجب ترتيب الـ tuple الخاص بـ ORDER BY حسب الكاردينالية تصاعديًا
  • إذا وُجد، فيجب أن يكون الـ tuple الخاص بـ PRIMARY KEY مجموعة فرعية من الـ tuple الخاص بـ ORDER BY
  • إذا جرى تحديد ORDER BY فقط، فسيُستخدم الـ tuple نفسه بوصفه PRIMARY KEY
  • يُنشأ فهرس المفتاح الأساسي باستخدام الـ tuple الخاص بـ PRIMARY KEY إذا كان محددًا، وإلا فباستخدام الـ tuple الخاص بـ ORDER BY
  • يُحتفَظ بفهرس PRIMARY KEY في الذاكرة الرئيسية
عند النظر إلى مجموعة البيانات والأسئلة التي يمكن الإجابة عنها من خلال الاستعلام عنها، قد نقرر أننا سننظر في أنواع الجرائم المُبلَّغ عنها بمرور الوقت في أحياء بورو الخمسة لمدينة نيويورك. ويمكن عندئذٍ تضمين هذه الحقول في ORDER BY: الاستعلام عن ملف TSV لمعرفة الكاردينالية للأعمدة الثلاثة المرشحة:
Query
Response
عند الترتيب حسب الكاردينالية، يصبح ORDER BY كما يلي:
سيستخدم الجدول أدناه أسماء أعمدة أسهل قراءةً، وستُطابَق الأسماء الواردة أعلاه مع
بجمع التغييرات على أنواع البيانات مع Tuple الخاصة بـ ORDER BY، نحصل على بنية الجدول التالية:

العثور على المفتاح الأساسي لجدول ما

تحتوي قاعدة البيانات system في ClickHouse، وتحديدًا system.table، على جميع المعلومات المتعلقة بالجدول الذي أنشأته للتو. يوضّح هذا الاستعلام ORDER BY (مفتاح الترتيب)، وPRIMARY KEY:
الاستجابة

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

سنستخدم أداة clickhouse-local لإجراء المعالجة المسبقة للبيانات، وclickhouse-client لتحميلها.

وسائط clickhouse-local المستخدمة

يظهر table='input' في وسائط clickhouse-local أدناه. يأخذ clickhouse-local الإدخال الموفَّر (cat ${HOME}/NYPD_Complaint_Data_Current__Year_To_Date_.tsv) ويُدرجه في جدول. ويكون اسم الجدول افتراضيًا table. في هذا الدليل، ضُبط اسم الجدول على input لتوضيح تدفق البيانات بشكل أفضل. أما الوسيطة الأخيرة لـ clickhouse-local فهي استعلام يحدد البيانات من الجدول (FROM input)، ثم يُمرَّر إلى clickhouse-client لملء الجدول NYPD_Complaint.

تحقّق من البيانات

تتغير مجموعة البيانات مرة واحدة أو أكثر سنويًا، لذا قد لا تتطابق أعدادك مع ما يرد في هذا المستند.
Query
Response
حجم مجموعة البيانات في ClickHouse لا يزيد عن 12% من ملف TSV الأصلي، قارن حجم ملف TSV الأصلي بحجم الجدول:
Query
Response

نفّذ بعض الاستعلامات

الاستعلام 1. قارن عدد الشكاوى حسب الأشهر

Query
Response

الاستعلام 2. قارن إجمالي عدد الشكاوى حسب البورو

Query
Response

الخطوات التالية

تستعرض مقدمة عملية عن الفهارس الأولية المتناثرة في ClickHouse الاختلافات بين الفهرسة في ClickHouse والفهرسة في قواعد البيانات العلائقية التقليدية، وكيفية إنشاء ClickHouse لفهرس أولي متناثر واستخدامه، وأفضل ممارسات الفهرسة.
آخر تعديل في ١ يوليو ٢٠٢٦