الانتقال إلى المحتوى الرئيسي
تتضمن عبارة ORDER BY ما يلي:
  • قائمة من التعبيرات، مثل ORDER BY visits, search_phrase,
  • قائمة من الأرقام التي تشير إلى الأعمدة في عبارة SELECT، مثل ORDER BY 2, 1، أو
  • ALL، وتعني جميع أعمدة عبارة SELECT، مثل ORDER BY ALL.
لتعطيل الفرز حسب أرقام الأعمدة، اضبط الإعداد enable_positional_arguments = 0. ولتعطيل الفرز حسب ALL، اضبط الإعداد enable_order_by_all = 0. يمكن أن تقترن عبارة ORDER BY بالمُعدِّل DESC (تنازلي) أو ASC (تصاعدي)، والذي يحدد اتجاه الفرز. ما لم يُحدَّد ترتيب فرز صريح، يُستخدم ASC افتراضيًا. وينطبق اتجاه الفرز على تعبير واحد، لا على القائمة بأكملها، مثل ORDER BY Visits DESC, SearchPhrase. كذلك، يُجرى الفرز مع مراعاة حالة الأحرف. تُعاد الصفوف ذات القيم المتطابقة في تعبيرات الفرز بترتيب عشوائي وغير حتمي. وإذا حُذفت عبارة ORDER BY من جملة SELECT، فسيكون ترتيب الصفوف أيضًا عشوائيًا وغير حتمي.

فرز القيم الخاصة

هناك نهجان لترتيب NaN وNULL عند الفرز:
  • افتراضيًا أو مع المُعدِّل NULLS LAST: تأتي القيم أولًا، ثم NaN، ثم NULL.
  • مع المُعدِّل NULLS FIRST: يأتي NULL أولًا، ثم NaN، ثم القيم الأخرى.

مثال

للجدول
نفّذ الاستعلام SELECT * FROM t_null_nan ORDER BY y NULLS FIRST للحصول على:
عند فرز الأعداد ذات الفاصلة العائمة، تكون قيم NaN منفصلة عن القيم الأخرى. وبغضّ النظر عن ترتيب الفرز، تأتي قيم NaN في النهاية. وبعبارة أخرى، عند الفرز تصاعديًا تُوضَع كما لو كانت أكبر من جميع الأعداد الأخرى، بينما عند الفرز تنازليًا تُوضَع كما لو كانت أصغر من سائر القيم.

دعم قواعد الترتيب

لفرز قيم String، يمكنك تحديد قواعد الترتيب (المقارنة). مثال: ORDER BY SearchPhrase COLLATE 'tr' - لفرز keyword بترتيب تصاعدي باستخدام الأبجدية التركية، مع تجاهل حالة الأحرف، على افتراض أن السلاسل مرمّزة بترميز UTF-8. يمكن تحديد COLLATE أو عدم تحديده لكل تعبير في ORDER BY بشكل مستقل. إذا تم تحديد ASC أو DESC، فيتم وضع COLLATE بعده. عند استخدام COLLATE، يكون الفرز دائمًا غير حساس لحالة الأحرف. تدعم LowCardinality وNullable وArray وTuple استخدام COLLATE. نوصي باستخدام COLLATE فقط للفرز النهائي لعدد صغير من الصفوف، لأن الفرز باستخدام COLLATE أقل كفاءة من الفرز العادي حسب البايتات.

أمثلة على قواعد الترتيب

مثال يقتصر على قيم String فقط: جدول الإدخال:
Query
Response
مثال على Nullable: جدول المُدخلات:
Query
Response
مثال باستخدام Array: جدول الإدخال:
Query
Response
مثال باستخدام سلسلة نصية LowCardinality: جدول الإدخال:
Query
Response
مثال على Tuple:
Response
Query
Response

تفاصيل التنفيذ

يُستخدم قدر أقل من ذاكرة RAM إذا جرى تحديد LIMIT صغير بما يكفي إلى جانب ORDER BY. بخلاف ذلك، تكون كمية الذاكرة المستخدمة متناسبة مع حجم البيانات المطلوب فرزها. في المعالجة الموزعة للاستعلامات، إذا تم حذف GROUP BY، يُنفَّذ جزء من الفرز على الخوادم البعيدة، ثم تُدمَج النتائج على الخادم الذي أرسل الطلب. وهذا يعني أنه في الفرز الموزع قد يكون حجم البيانات المطلوب فرزها أكبر من مقدار الذاكرة المتاح على خادم واحد. إذا لم تكن ذاكرة RAM كافية، فمن الممكن إجراء الفرز باستخدام الذاكرة الخارجية (بإنشاء ملفات مؤقتة على قرص). استخدم الإعداد max_bytes_before_external_sort لهذا الغرض. إذا كانت قيمته 0 (وهي القيمة الافتراضية)، فسيتم تعطيل الفرز الخارجي. وإذا كان مفعّلًا، فعندما يصل حجم البيانات المطلوب فرزها إلى عدد البايتات المحدد، تُفرَز البيانات المجمَّعة وتُحفَظ في ملف مؤقت. وبعد قراءة جميع البيانات، تُدمَج جميع الملفات المفروزة وتُخرَج النتائج. تُكتَب الملفات في الدليل /var/lib/clickhouse/tmp/ ضمن config (افتراضيًا، ولكن يمكنك استخدام المعلمة tmp_path لتغيير هذا الإعداد). يمكنك أيضًا استخدام الكتابة إلى القرص فقط إذا تجاوز الاستعلام حدود الذاكرة؛ أي إن max_bytes_ratio_before_external_sort=0.6 سيؤدي إلى تفعيل الكتابة إلى القرص فقط عندما يبلغ الاستعلام 60% من حد الذاكرة (user/sever). قد يستهلك تشغيل الاستعلام ذاكرة أكبر من max_bytes_before_external_sort. ولهذا السبب، يجب أن تكون قيمة هذا الإعداد أقل بكثير من max_memory_usage. على سبيل المثال، إذا كان لدى خادمك 128 غيغابايت من ذاكرة RAM وكنت بحاجة إلى تشغيل استعلام واحد، فاضبط max_memory_usage على 100 غيغابايت، وmax_bytes_before_external_sort على 80 غيغابايت. يعمل الفرز الخارجي بكفاءة أقل بكثير من الفرز داخل ذاكرة RAM.

تحسين قراءة البيانات

إذا كان لتعبير ORDER BY بادئة تتطابق مع مفتاح فرز الجدول، يمكنك تحسين الاستعلام باستخدام إعداد optimize_read_in_order. عند تمكين إعداد optimize_read_in_order، يستخدم خادم ClickHouse فهرس الجدول ويقرأ البيانات وفق ترتيب مفتاح ORDER BY. يتيح ذلك تجنب قراءة جميع البيانات عند تحديد LIMIT. لذلك، تُعالَج الاستعلامات على البيانات الكبيرة ذات LIMIT صغير بشكل أسرع. يعمل هذا التحسين مع كلٍّ من ASC وDESC، ولا يعمل مع بند GROUP BY ومُعدِّل FINAL معًا. عند تعطيل إعداد optimize_read_in_order، لا يستخدم خادم ClickHouse فهرس الجدول أثناء معالجة استعلامات SELECT. فكّر في تعطيل optimize_read_in_order يدويًا عند تشغيل استعلامات تحتوي على عبارة ORDER BY وLIMIT كبير وشرط WHERE يتطلب قراءة كمية هائلة من السجلات قبل العثور على البيانات المطلوبة. التحسين مدعوم في محركات الجداول التالية: في الجداول التي تستخدم المحرك MaterializedView، يعمل هذا التحسين مع العروض مثل SELECT ... FROM merge_tree_table ORDER BY pk. لكنه غير مدعوم في استعلامات مثل SELECT ... FROM view ORDER BY pk إذا كان استعلام العرض لا يحتوي على عبارة ORDER BY.

مُعدِّل ORDER BY Expr WITH FILL

يمكن أيضًا دمج هذا المُعدِّل مع مُعدِّل LIMIT … WITH TIES. يمكن استخدام مُعدِّل WITH FILL بعد ORDER BY expr مع مَعلمات اختيارية هي FROM expr وTO expr وSTEP expr. ستُملأ جميع القيم الناقصة في العمود expr بالتسلسل، وستُملأ الأعمدة الأخرى بالقيم الافتراضية. لملء أعمدة متعددة، أضِف مُعدِّل WITH FILL مع مَعلمات اختيارية بعد اسم كل عمود في قسم ORDER BY.
Query
يمكن تطبيق WITH FILL على الحقول ذات الأنواع Numeric ‏(بجميع أنواع float وdecimal وint) أو الأنواع Date/DateTime. وعند تطبيقه على حقول String، تُملأ القيم المفقودة بسلاسل فارغة. عندما لا يكون FROM const_expr محددًا، يستخدم تسلسل الملء الحد الأدنى لقيمة الحقل expr من ORDER BY. عندما لا يكون TO const_expr محددًا، يستخدم تسلسل الملء الحد الأقصى لقيمة الحقل expr من ORDER BY. عندما يكون STEP const_numeric_expr محددًا، يُفسَّر const_numeric_expr as is للأنواع الرقمية، وdays لنوع Date، وseconds لنوع DateTime. كما يدعم أيضًا نوع البيانات INTERVAL الذي يمثل فواصل زمنية للتاريخ والوقت. عندما يتم إغفال STEP const_numeric_expr، يستخدم تسلسل الملء 1.0 للنوع الرقمي، و1 day لنوع Date، و1 second لنوع DateTime. عندما يكون STALENESS const_numeric_expr محددًا، سينشئ الاستعلام صفوفًا إلى أن يتجاوز الفرق عن الصف السابق في البيانات الأصلية const_numeric_expr. يمكن تطبيق INTERPOLATE على الأعمدة التي لا تشارك في ORDER BY WITH FILL. وتُملأ هذه الأعمدة استنادًا إلى قيم الحقول السابقة عبر تطبيق expr. وإذا لم يكن expr موجودًا، فستُكرَّر القيمة السابقة. ويؤدي إغفال القائمة إلى تضمين جميع الأعمدة المسموح بها. مثال على استعلام بدون WITH FILL:
Query
Response
الاستعلام نفسه بعد تطبيق المُعدِّل WITH FILL:
Query
Response
في حالة وجود عدة حقول في ORDER BY field2 WITH FILL, field1 WITH FILL، سيكون ترتيب الملء وفق ترتيب الحقول في عبارة ORDER BY. مثال:
Query
Response
الحقل d1 لا يُملأ ولا يستخدم القيمة الافتراضية لأنّه لا توجد قيم متكررة في d2، ولا يمكن حساب تسلسل d1 بشكل صحيح. الاستعلام التالي بعد تغيير الحقل في ORDER BY:
Query
Response
يستخدم الاستعلام التالي نوع البيانات INTERVAL بقيمة يوم واحد لكل قيمة بيانات يتم ملؤها في العمود d1:
Query
Response
مثال لاستعلام بدون STALENESS:
Query
Response
الاستعلام نفسه بعد تطبيق STALENESS 3:
Query
Response
مثال لاستعلام بدون INTERPOLATE:
Query
Response
الاستعلام نفسه بعد تطبيق INTERPOLATE:
Query
Response

الملء للمجموعات بحسب بادئة الترتيب

قد يكون من المفيد ملء الصفوف التي تتطابق قيمها في أعمدة معيّنة بشكل مستقل — ومن الأمثلة الجيدة على ذلك ملء القيم المفقودة في السلاسل الزمنية. لنفترض وجود جدول السلاسل الزمنية التالي:
ونودّ ملء القيم المفقودة لكل مستشعر بشكل مستقل وعلى فواصل زمنية قدرها ثانية واحدة. ولتحقيق ذلك، نستخدم العمود sensor_id كبادئة للفرز للعمود timestamp عند الملء:
هنا، جرى إدراج القيمة 9999 في العمود value فقط لجعل الصفوف التي جرى ملؤها أكثر وضوحًا. يُتحكَّم في هذا السلوك عبر ضبط use_with_fill_by_sorting_prefix (مفعّل افتراضيًا)
آخر تعديل في ٢٥ يونيو ٢٠٢٦