JOIN جدولًا جديدًا من خلال دمج الأعمدة من جدول واحد أو عدة جداول باستخدام القيم المشتركة بينها. وهي عملية شائعة في قواعد البيانات التي تدعم SQL، وتقابل عملية join في الجبر العلاقي. وغالبًا ما يُشار إلى الحالة الخاصة المتمثلة في ربط جدول بنفسه باسم “self-join”.
البنية
ON والأعمدة الواردة في عبارة USING “مفاتيح الربط”. ما لم يُذكر خلاف ذلك، فإن JOIN يُنتج حاصل ضرب ديكارتيًا من الصفوف ذات “مفاتيح الربط” المتطابقة، وقد يؤدي ذلك إلى نتائج تضم عددًا من الصفوف أكبر بكثير من الجداول المصدرية.
أنواع JOIN المدعومة
جميع أنواع SQL JOIN القياسية مدعومة:- يشير
JOINمن دون تحديد نوع إلىINNER. - يمكن حذف الكلمة المفتاحية
OUTERبأمان. - من الصيغ البديلة لـ
CROSS JOINتحديد عدة جداول فيFROMclause مفصولة بفواصل. - إذا لم تكن هناك أعمدة متطابقة لـ
NATURAL JOIN، فإنه يعمل مثلCROSS JOIN.
عند استخدام المحلّل (analyzer)، يؤدي تعطيل الإعداد
semi_join_include_columns_from_both_sides أو anti_join_include_columns_from_both_sides إلى أن يقتصر الربط المعني على إتاحة جانبه المحفوظ فقط للتعابير التي تُحلَّل بعد تكوين نتيجة الربط.- يُتيح
LEFT SEMI JOINوLEFT ANTI JOINأعمدة الجانب الأيسر فقط. - يُتيح
RIGHT SEMI JOINوRIGHT ANTI JOINأعمدة الجانب الأيمن فقط. - يؤثر ذلك في عبارات مثل
SELECTوPREWHEREوWHEREوGROUP BYوHAVINGوQUALIFYوORDER BYوLIMIT BY، بما في ذلك محارف البدل المؤهَّلة مثلt1.*. - يظل بإمكان تعبير
ONالخاص بـJOINنفسه الإشارة إلى كلا الجانبين.
SELECT * الأعمدة من كلا الجدولين.عند ضبط join_algorithm على
partial_merge، لا يكون RIGHT JOIN وFULL JOIN مدعومَين إلا مع صرامة من النوع ALL (SEMI وANTI وANY وASOF غير مدعومة).LATERAL JOIN
يتيحJOIN LATERAL للاستعلام الفرعي الواقع على الجانب الأيمن من عملية الربط أن يشير إلى أعمدة تعبيرات الجداول
الواقعة على يساره؛ إذ يُقيَّم الاستعلام الفرعي مرةً لكل تركيبة مميزة من قيم أعمدة الجانب الأيسر
التي يشير إليها، ثم تُربط نتيجته بكل صف من صفوف الجانب الأيسر يحمل التركيبة نفسها:
ON true إلزامي، كما هو الحال في أي INNER أو LEFT JOIN آخر؛ وحذفه يُعدّ خطأً نحويًا.
هذه الميزة تجريبية ومعطّلة افتراضيًا؛ ويمكن تفعيلها عبر الإعداد
allow_experimental_lateral_join.
لا تُدعم حتى الآن سوى المجموعة الفرعية التالية؛ وكل ما عداها يُرفض مع ظهور خطأ:
INNER JOIN LATERALوLEFT JOIN LATERALفقط؛ ولا تُدعم عمليات الربط من نوعRIGHTوFULLوPASTEوNATURAL، ولا يمكن إطلاقًا الجمع بينLATERALوربطCROSSأو الربط بالفاصلة.- الصرامة الافتراضية
ALLفقط؛ ولا تُدعمANYوSEMIوANTIوASOF. - لا يُسمح بأي مسند ربط غير
ON true(يُقبلON 1أيضًا)؛ ولا يُدعمUSING، ولا يمكن حذف المسند. ضع شروط التصفية التي تربط بين الطرفين في عبارةWHEREالخاصة بالاستعلام الفرعي الجانبي. - لا تُدعم مُعدِّلات الربط
GLOBALوLOCAL. - يجب أن يشير الاستعلام الفرعي الجانبي إلى عمود واحد على الأقل من الطرف الأيسر. أما الاستعلام الفرعي غير المترابط فاستخدم معه ربطًا عاديًا.
- يُقيَّم الاستعلام الفرعي الجانبي مرة واحدة لكل قيمة مميزة من قيم أعمدة الطرف الأيسر التي يشير إليها، لا
مرة لكل صف من الطرف الأيسر؛ لذا يجب ألا يحتوي على دوال غير حتمية ضمن الاستعلام، مثل
randأوgenerateUUIDv4، ولا على دالات جداول تولّد صفوفًا عشوائية، مثلgenerateRandom. أما الدوال الثابتة ضمن الاستعلام، مثلnow، فمسموح بها. - لا يُدعم بوصفه تعبير الجدول الجانبي إلا الاستعلام الفرعي. ولا تُدعم صيغ مصادر الجداول المستخدمة في PostgreSQL
مثل
LATERAL unnest(...)وCROSS JOIN UNNEST(...)- استخدم بدلًا منها عبارةARRAY JOIN. - يُنفَّذ
GROUP BYوORDER BYالخاصان بالاستعلام الفرعي الجانبي مرة واحدة على جميع عمليات التقييم مجتمعةً، لذا فإن الحدودmax_rows_to_group_byوmax_rows_to_sortوmax_bytes_to_sortتحتسب صفوف جميع عمليات التقييم، لا صفوف عملية واحدة فقط. ولا تُدعم هذه الحدود إلا مع وضع التجاوزthrow؛ أماanyوbreakفيُرفضان. - تُطابَق صفوف جميع عمليات التقييم مع صفوف الطرف الأيسر عبر عملية ربط واحدة. وكما في أي ربط بالتجزئة،
يقيّد
max_rows_in_joinوmax_bytes_in_joinالطرفَ الذي يُحتفظ به في الذاكرة من هذا الربط، ويتولى المخطِّط اختيار هذا الطرف: مع الإعدادات الافتراضية (correlated_subqueries_use_in_memory_buffer = 1) يكون الطرف الأيسر منJOIN LATERAL، لأن صفوف الطرف الأيسر يجب أن تُقرأ كاملةً قبل تقييم الاستعلام الفرعي الجانبي؛ وإلا فقد يكون نتائج جميع عمليات التقييم مجتمعةً. وتُطبَّق الحدود دائمًا كما لو كانت قيمةjoin_overflow_modeهيthrow، إذ إن الربط معbreakسيُسقط بصمت صفوفًا من الطرف الأيسر لا علاقة لها بالأمر.
الإعدادات
يمكن تجاوز نوعJOIN الافتراضي باستخدام الإعداد join_default_strictness.
يعتمد سلوك ClickHouse server في عمليات ANY JOIN على الإعداد any_join_distinct_right_table_keys.
انظر أيضًا
join_algorithmjoin_any_take_last_rowjoin_use_nullspartial_merge_join_rows_in_right_blocksjoin_on_disk_max_files_to_mergeany_join_distinct_right_table_keys
cross_to_inner_join_rewrite لتحديد السلوك عند فشل ClickHouse في إعادة كتابة CROSS JOIN إلى INNER JOIN. القيمة الافتراضية هي 1، ما يسمح بمتابعة عملية JOIN ولكنها ستكون أبطأ. اضبط cross_to_inner_join_rewrite على 0 إذا كنت تريد ظهور خطأ، واضبطه على 2 لعدم تشغيل عمليات cross joins، وبدلًا من ذلك فرض إعادة كتابة جميع عمليات comma/cross joins. وإذا فشلت إعادة الكتابة عندما تكون القيمة 2، فستتلقى رسالة خطأ تنص على: “Please, try to simplify WHERE section”.
شروط قسم ON
يمكن أن يحتوي قسم ON على عدة شروط مدمجة باستخدام المعاملين AND وOR. ويجب أن تستوفي الشروط التي تحدد مفاتيح الربط ما يلي:
- أن تشير إلى كلٍّ من الجدول الأيسر والجدول الأيمن
- أن تستخدم معامل المساواة
JOIN. لاحظ أنه إذا وُضعت الشروط نفسها في قسم WHERE ولم تتحقق، فستُستبعد الصفوف دائمًا من النتيجة.
يعمل المعامل OR داخل عبارة ON باستخدام خوارزمية الربط بالتجزئة — إذ يُنشأ جدول تجزئة منفصل لكل وسيطة OR تحتوي على مفاتيح ربط لـ JOIN، لذلك يزداد استهلاك الذاكرة ووقت تنفيذ الاستعلام خطيًا مع زيادة عدد تعبيرات OR في عبارة ON.
معامل المساواة (
=) وحده هو ما يجعل الشرط مفتاح ربط. والمعاملات الأخرى بين أعمدة من جداول مختلفة مدعومة، لكن في غياب أي شرط مساواة يتعيّن على عملية الربط فحص كل زوج من الصفوف، فتصبح أبطأ بكثير؛ راجع JOIN مع شرط ON عشوائي.table_1 وtable_2:
table_2:
Query
C وعمود النص الفارغ. وقد أُدرجت في النتيجة لأن نوع OUTER من join مستخدم هنا.
Response
INNER وبشروط متعددة:
Query
Response
join من النوع INNER وشرط يستخدم OR:
Query
Response
INNER وبشروط تتضمن OR وAND:
يُطبَّق شرط عدم المساواة الذي يستخدم أعمدة من جدول واحد، مثل
t1.a = t2.key AND t1.b > 0 AND t2.b > t2.c، على ذلك الجدول وحده: إذ يستخدم t1.b > 0 أعمدة من t1 فقط، وt2.b > t2.c يستخدم أعمدة من t2 فقط.
كما أن شروط عدم المساواة التي تقارن أعمدة من جداول مختلفة، مثل t1.a = t2.key AND t1.b > t2.key، مدعومة كذلك؛ راجع الأقسام أدناه لمزيد من التفاصيل.Query
Response
JOIN مع شروط عدم المساواة للأعمدة من جداول مختلفة
يدعم ClickHouse ALL/ANY/SEMI/ANTI INNER/LEFT/RIGHT/FULL JOIN مع شروط عدم المساواة بالإضافة إلى شروط المساواة.
عندما يحتوي قسم ON على شرط مساواة بين الجدولين إلى جانب شرط عدم المساواة، يكون شرط المساواة هو مفتاح الربط، ويُتحقَّق من شرط عدم المساواة على الصفوف التي طابقها. ولا يُنفَّذ هذا الشرط المختلط إلا بواسطة خوارزميات الربط hash وparallel_hash وgrace_hash.
عندما لا يحتوي قسم ON على أي شرط مساواة بين الجدولين، فلا يوجد مفتاح ربط تُجرى المطابقة على أساسه. ويُنفَّذ هذا الربط بواسطة ie_join عندما يكون الشرط زوجًا من شروط عدم المساواة، وإلا فيُنفَّذ بوصفه ربطًا بحلقات متداخلة على مستوى الكتل.
لا يجوز أن يحتوي الشرط الذي يُقيَّم أثناء الربط على arrayJoin، إذ يجب أن يحافظ على عدد الصفوف؛ استخدم بدلًا من ذلك ARRAY JOIN في استعلام فرعي.
مثال
الجدول t1:
t2
JOIN مع شرط ON عشوائي
يمكن أن يكون قسمON أي تعبير منطقي على أعمدة الجدولين، مثل التحقق من نطاق، أو مقارنة حسابية، أو استدعاء دالة مفردة. وإذا لم يتضمن أي مساواة بين الجدولين، فلن يوجد مفتاح ربط تُطابَق الصفوف على أساسه. ويُنفَّذ زوج من شروط عدم المساواة باستخدام ie_join عندما تكون هذه الخوارزمية مدرجة في join_algorithm، وهو ما يحدث افتراضيًا. أما أي شرط آخر فيُنفَّذ بوصفه ربطًا بحلقات متداخلة على مستوى الكتل، إذ يُجسَّد الجدول الأيمن ثم يُقيَّم الشرط على كل زوج من الصفوف. ويأخذ ALL INNER JOIN في هذه الحالة صيغة مكافئة لـ CROSS JOIN يُستخدم فيها الشرط عاملَ تصفية.
يدعم الربط بحلقات متداخلة على مستوى الكتل جميع أنواع الربط ومستويات الصرامة باستثناء ASOF JOIN وPASTE JOIN وANY FULL JOIN. وهو ليس من قيم join_algorithm، بل هو الملاذ الأخير الذي لا يُلجأ إليه إلا عندما تعجز الخوارزميات الأخرى عن تنفيذ الشرط. ويظهر في إخراج EXPLAIN على هيئة خطوة BlockNestedLoopJoin. وعند تعطيل allow_block_nested_loop_join، يُرفض أي استعلام يتطلبه ويُعاد الخطأ INVALID_JOIN_ON_EXPRESSION.
مثال
Query
Response
join_use_nulls، كما هو الحال في أي ربط آخر: بقيمة افتراضية كما في المثال أعلاه، وبـ NULL عند تفعيل هذا الإعداد.
الصرامة
يحتفظ ANY وSEMI عادةً بصف واحد لكل مجموعة من الصفوف التي تشترك في مفتاح الربط نفسه. ولمّا كانت هذه المجموعة غير موجودة هنا، فإنهما يحتفظان بصف واحد لكل صف من الجدول الذي يقود الربط: يُخرج LEFT ANY وLEFT SEMI كل صف أيسر مرة واحدة على الأكثر، ويُخرج RIGHT ANY وRIGHT SEMI كل صف أيمن مرة واحدة على الأكثر. أما ANY INNER فيقيّد الجانبين معًا — إذ يُستخدم كل صف من كلا الجدولين مرة واحدة على الأكثر، فلا يتجاوز عدد صفوف النتيجة عدد صفوف الجدول الأصغر. ويكون اختيار الأزواج التي تُكوّن هذه النتيجة اعتباطيًا، تمامًا كما يقتضي ANY، وقد يختلف بين تشغيلين للاستعلام نفسه. وفي حالة ANY INNER يمتد ذلك ليشمل عدد الصفوف أيضًا: فإقران صفوف الجانبين بطريقة جشعة، بأي ترتيب تُفحص به الصفوف، قد يترك عددًا مختلفًا من الصفوف دون إقران، ولذلك فإن نتيجة count() على ربط ANY INNER بلا مفتاح ربط غير قابلة للتكرار، وتتوقف على عدد خيوط التنفيذ وعلى الترتيب الفعلي لصفوف الجدول الأيمن.
الأداء
يُفحص كل زوج من الصفوف، لذا يتزايد حجم العمل بحسب حاصل ضرب عددَي صفوف الجدولين لا بحسب مجموعهما. ومن ثَمّ فإن الربط بالحلقات المتداخلة على مستوى الكتل أعلى تكلفة بمراتب عديدة من الربط بالتجزئة على البيانات نفسها، وتتسع الفجوة كلما كبر حجم الجداول. فإذا أمكن كتابة الاستعلام بشرط مساواة واحد على الأقل في قسم ON، فاكتبه على هذا النحو.
تتوقف عمليات الربط LEFT ANY وANY INNER وLEFT SEMI وLEFT ANTI عن فحص الجدول الأيمن عند أول صف يطابق الصف الأيسر، مما يجعلها عادةً أقل تكلفة من ربط ALL المقابل. أما نظيراتها التي يقودها الجانب الأيمن (RIGHT ANY وRIGHT SEMI وRIGHT ANTI) فتفحص كل الأزواج، لأن النتيجة تتوقف على الصفوف اليمنى التي وُجدت لها مطابقة. ولا أثر للإعداد join_any_take_last_row هنا: فعند غياب مفتاح الربط لا توجد مجموعة من الصفوف المطابقة يُؤخذ آخرها.
يظل استهلاك الذاكرة محدودًا بحجم الجدول الأيمن المُجسَّد، ولا يزداد بازدياد حجم النتيجة. ويخضع الجدول الأيمن للإعدادات نفسها المطبقة في خوارزميات الربط الأخرى، والمذكورة في قسم قيود الذاكرة: إذ تُقيّد حجمَه الإعدادات max_rows_in_join وmax_bytes_in_join وjoin_overflow_mode، في حين يؤدي الإعداد max_bytes_before_external_join إلى كتابته على القرص.
قيم NULL وNaN في مفاتيح الربط
لا تساوي NULL أي قيمة، بما في ذلك نفسها. وهذا يعني أنه إذا كانت قيمة مفتاح الربط هي NULL في أحد الجدولين، فلن تطابق قيمة NULL في الجدول الآخر.
مثال
الجدول A:
B:
Charlie من الجدول A، والصف الذي درجته 88 من الجدول B، لا يظهران في النتيجة بسبب القيمة NULL في مفتاح الربط.
إذا أردت مطابقة قيم NULL، فاستخدم الدالة isNotDistinctFrom لمقارنة مفاتيح الربط.
NaN في مفاتيح الربط من نوع float قاعدة NULL المذكورة أعلاه.
تكون المقارنة القياسية بين قيمتي NaN (NaN = NaN) هي 0، لكن لا تُقارن مفاتيح الربط وفق دلالات المقارنة القياسية؛ وقد تتطابق مفاتيح NaN.
وما إذا كانت تتطابق فعليًا يعتمد على تفاصيل التنفيذ وخوارزمية الربط ونوع المفتاح وإعدادات الجلسة.
لا تعتمد على سلوك محدد.
إذا كنت تحتاج إلى عدم تطابق الصفوف التي تحتوي على NaN، فحوّلها إلى قيم NULL: ON if(isNaN(A.id), NULL, A.id) = B.id.
في ASOF JOIN، يُقارن العمود الخاص بأقرب تطابق وفق الترتيب، وهو ما لا تدعمه NaN — لذا رشّح هذه الصفوف من كلا الجانبين.
استخدام ASOF JOIN
تُعدASOF JOIN مفيدة عندما تحتاج إلى ربط سجلات لا يوجد بينها تطابق تام.
تتطلب خوارزمية JOIN هذه عمودًا خاصًا في الجداول. ويجب أن يكون هذا العمود:
- أن يحتوي على تسلسل مرتب.
- من أحد الأنواع التالية: Int, UInt، Float، Date، DateTime، Decimal.
- بالنسبة إلى خوارزمية
hashjoin، لا يمكن أن يكون العمود الوحيد في عبارةJOIN.
ASOF JOIN ... ON:
SELECT count() FROM table_1 ASOF LEFT JOIN table_2 ON table_1.a == table_2.b AND table_2.t <= table_1.t.
الشروط المدعومة لأقرب مطابقة: >, >=, <, <=.
الصياغة ASOF JOIN ... USING:
ASOF JOIN equi_columnX للربط وفقًا للمساواة، وasof_column للربط بأقرب قيمة مطابقة مع الشرط table_1.asof_column >= table_2.asof_column. ويكون العمود asof_column دائمًا هو الأخير في بند USING.
على سبيل المثال، تأمل الجداول التالية:
ASOF JOIN أخذ الطابع الزمني لحدث مستخدم من table_1 والعثور على حدث في table_2 يكون طابعه الزمني الأقرب إلى الطابع الزمني لحدث table_1 وفقًا لشرط أقرب تطابق. وتُعد قيم الطابع الزمني المتساوية هي الأقرب إذا كانت متاحة. هنا، يمكن استخدام العمود user_id للربط على أساس المساواة، ويمكن استخدام العمود ev_time للربط على أساس أقرب تطابق. في مثالنا، يمكن ربط event_1_1 مع event_2_1، ويمكن ربط event_1_2 مع event_2_3، لكن لا يمكن ربط event_2_2.
لا يدعم
ASOF JOIN إلا خوارزميتي JOIN hash وfull_sorting_merge.
وهو غير مدعوم في محرك الجدول Join.استخدام PASTE JOIN
نتيجةPASTE JOIN هي جدول يحتوي على جميع الأعمدة من الاستعلام الفرعي الأيسر، ثم جميع الأعمدة من الاستعلام الفرعي الأيمن.
تُطابَق الصفوف بناءً على مواضعها في الجداول الأصلية (يجب أن يكون ترتيب الصفوف محددًا).
إذا أعادت الاستعلامات الفرعية أعدادًا مختلفة من الصفوف، فستُقتطع الصفوف الزائدة.
مثال:
JOIN الموزّع
توجد طريقتان لتنفيذJOIN يتضمن جداول موزعة:
- عند استخدام
JOINعادي، يُرسَل الاستعلام إلى الخوادم البعيدة. وتُشغَّل الاستعلامات الفرعية على كل خادم منها لتكوين الجدول الأيمن، ثم تُنفَّذ عملية الربط باستخدام هذا الجدول. وبعبارة أخرى، يُنشأ الجدول الأيمن على كل خادم على حدة. - عند استخدام
GLOBAL ... JOIN، يشغّل الخادم الذي أرسل الطلب أولًا استعلامًا فرعيًا لحساب أحد طرفَي الربط ويجمع النتيجة في جدول مؤقت. ثم يُمرَّر هذا الجدول المؤقت إلى كل خادم بعيد، وتُشغَّل الاستعلامات عليها باستخدام البيانات المؤقتة المنقولة. في عمليتَي الربطLEFTوINNER، يُحسَب الجدول الأيمن باعتباره الاستعلام الفرعي. أما في عملية الربطRIGHT، فيُحسَب الجدول الأيسر بدلًا من ذلك، لأن الجدول الأيمن هو الجدول الذي يجري الاحتفاظ به ويجب قراءته من الشظايا.
GLOBAL. لمزيد من المعلومات، راجع قسم الاستعلامات الفرعية الموزعة.
تحويل النوع الضمني
تدعم استعلاماتINNER JOIN وLEFT JOIN وRIGHT JOIN وFULL JOIN تحويل النوع الضمني لـ “join keys”. ومع ذلك، لا يمكن تنفيذ الاستعلام إذا تعذر تحويل مفاتيح الربط في الجدولين الأيسر والأيمن إلى نوع واحد (على سبيل المثال، لا يوجد نوع بيانات يمكنه استيعاب جميع القيم من كلٍّ من UInt64 وInt64، أو String وInt32).
مثال
لنأخذ الجدول t_1:
t_2:
توصيات الاستخدام
معالجة الخلايا الفارغة أو NULL
أثناء ربط الجداول، قد تظهر خلايا فارغة. يحدّد الإعداد join_use_nulls كيفية ملء ClickHouse لهذه الخلايا. إذا كانت مفاتيح الربطJOIN حقولًا من النوع Nullable، فلن تُربط الصفوف التي تكون قيمة واحد على الأقل من هذه المفاتيح فيها NULL.
البنية
يجب أن تحمل الأعمدة المحددة فيUSING الأسماء نفسها في كلا الاستعلامين الفرعيين، وأن تختلف أسماء الأعمدة الأخرى. يمكنك استخدام الأسماء المستعارة لتغيير أسماء الأعمدة في الاستعلامات الفرعية.
تحدّد عبارة USING عمودًا واحدًا أو أكثر للربط، وبذلك تفرض تساوي هذه الأعمدة. تُكتب قائمة الأعمدة من دون أقواس. ولا تُدعَم شروط ربط أكثر تعقيدًا.
قيود الصياغة
بالنسبة إلى عباراتJOIN المتعددة ضمن استعلام SELECT واحد:
- لا يتاح استخدام جميع الأعمدة عبر
*إلا إذا كان الربط بين جداول، لا استعلامات فرعية. - عبارة
PREWHEREغير متاحة. - عبارة
USINGغير متاحة.
ON وWHERE وGROUP BY:
- لا يمكن استخدام تعبيرات عشوائية في عبارات
ONوWHEREوGROUP BY، ولكن يمكنك تعريف تعبير في عبارةSELECTثم استخدامه في هذه العبارات عبر اسم مستعار.
الأداء
عند تنفيذJOIN، لا يوجد تحسين لترتيب التنفيذ بالنسبة إلى المراحل الأخرى من الاستعلام. ويُنفَّذ الـ join (أي البحث في الجدول الأيمن) قبل التصفية في WHERE وقبل التجميع.
في كل مرة يُنفَّذ فيها استعلام يستخدم JOIN نفسه، يُعاد تنفيذ الاستعلام الفرعي لأن النتيجة غير مخزنة مؤقتًا. ولتجنّب ذلك، استخدم محرك الجدول الخاص Join، وهو مصفوفة مُعدّة مسبقًا لعمليات الربط وتبقى دائمًا في ذاكرة RAM.
في بعض الحالات، يكون استخدام IN أكثر كفاءة من JOIN.
إذا كنت بحاجة إلى JOIN للربط مع جداول الأبعاد (وهي جداول صغيرة نسبيًا تحتوي على خصائص الأبعاد، مثل أسماء الحملات الإعلانية)، فقد لا يكون JOIN مناسبًا جدًا لأن الجدول الأيمن يُعاد الوصول إليه مع كل استعلام. في مثل هذه الحالات، توجد ميزة “Dictionaries” ينبغي استخدامها بدلًا من JOIN. لمزيد من المعلومات، راجع قسم Dictionaries.
قيود الذاكرة
افتراضيًا، يستخدم ClickHouse خوارزمية الربط بالتجزئة. يأخذ ClickHouse الجدول الأيمنright_table وينشئ له جدول تجزئة في RAM. إذا كان join_algorithm = 'auto' مفعّلًا، فبعد تجاوز عتبة معيّنة من استهلاك الذاكرة، يعود ClickHouse إلى خوارزمية merge join. للاطلاع على وصف خوارزميات JOIN، راجع الإعداد join_algorithm.
إذا كنت بحاجة إلى تقييد استهلاك الذاكرة لعملية JOIN، فاستخدم الإعدادات التالية:
- max_rows_in_join — يحدّ من عدد الصفوف في جدول التجزئة.
- max_bytes_in_join — يحدّ من حجم جدول التجزئة.
enable_adaptive_memory_spill_scheduler الذي لا يزال بإمكانه كتابة ربطٍ جعلته العتبة أدناه قابلًا للكتابة،
و
legacy_join_size_limits_trigger_spilling الذي يعيد الحدّين الصارمين إلى كونهما محفّزَين للكتابة على القرص.
للسماح للربط بالاستمرار عبر كتابة الجانب الأيمن على القرص بدلًا من الفشل، استخدم:
- max_bytes_before_external_join — عتبة كتابة مطلقة.
- max_bytes_ratio_before_external_join — عتبة الكتابة كنسبة من الذاكرة المتاحة.
grace_hash؛ وتحت ضغط الذاكرة
يمكن لـ enable_adaptive_memory_spill_scheduler أن يكتب على القرص أبكر مما يطلبانه — لكن فقط متى كان أحدهما
غير صفري، إذ إن الربط الذي لا عتبة له إطلاقًا لا يكتب على القرص أبدًا. وخوارزمية الربط join_algorithm التي تختارها
تحدّد كيفية كتابة الربط على القرص — إذ يقسّم grace_hash الجدول الأيمن ابتداءً من الكتلة الأولى، بينما يجمعه hash وparallel_hash
في الذاكرة ثم ينتقلان عند تجاوز العتبة — لا ما إذا كانت هذه الإعدادات تنطبق. والاستثناء الوحيد هو
legacy_join_size_limits_trigger_spilling: فعند تفعيله، يتجاهل grace_hash المستقل كلتا العتبتين ويكتب على القرص بناءً على الحدّين الصارمين بدلًا من ذلك.
أمثلة
مثال:محتوى ذو صلة
- مدونة: ClickHouse: نظام إدارة قواعد بيانات فائق السرعة مع دعم كامل لعمليات JOIN في SQL - الجزء 1
- مدونة: ClickHouse: نظام إدارة قواعد بيانات فائق السرعة مع دعم كامل لعمليات JOIN في SQL - خلف الكواليس - الجزء 2
- مدونة: ClickHouse: نظام إدارة قواعد بيانات فائق السرعة مع دعم كامل لعمليات JOIN في SQL - خلف الكواليس - الجزء 3
- مدونة: ClickHouse: نظام إدارة قواعد بيانات فائق السرعة مع دعم كامل لعمليات JOIN في SQL - خلف الكواليس - الجزء 4