أداء EXISTS مقابل IN
متى يتوقف EXISTS مبكرًا ويتفوق على IN، وهو سؤال متكرر في مقابلات الخبراء
أداء EXISTS مقابل IN درس مجاني في SQL Interview Prep على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في SQL Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
ما الذي يختبره EXISTS فعليًا
يأخذ EXISTS استعلامًا فرعيًا ويعيد true فور أن ينتج ذلك الاستعلام صفًا واحدًا على الأقل. ولا يهتم بالقيم المعادة — بل يهتم فقط بوجود أي صف.
- إنه اختبار منطقي يُستخدم في
WHERE. - ويكون دائمًا تقريبًا مرتبطًا: إذ يشير الاستعلام الداخلي إلى الصف الخارجي.
يظهر هذا السؤال المباشر في كل مقابلة تقريبًا لوظائف SQL المتوسطة إلى المتقدمة.
استعلام EXISTS أساسي
اعثروا على العملاء الذين أجروا طلبًا واحدًا على الأقل. يرتبط الاستعلام الداخلي بالشرط o.customer_id = c.id؛ ويعيد EXISTS القيمة true بمجرد العثور على طلب مطابق واحد.
لاحظوا SELECT 1 — فالقيمة المُسقطة غير مهمة، لذلك يكتب معظم المهندسين 1 أو *. يقبل المحاورون أيًّا منهما؛ فالمُحسِّن يتجاهل قائمة الاختيار داخل EXISTS.
SELECT c.name
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);سلوك الإيقاف المبكر
الكلمة التي يريد المحاورون سماعها هي short-circuit. يتوقف EXISTS عن فحص الاستعلام الداخلي لحظة العثور على صف مطابق واحد. ولا يحتاج أبدًا إلى إنشاء قائمة المطابقات الكاملة أو إزالة تكراراتها.
أما IN، فعلى المستوى المفاهيمي، ينشئ مجموعة القيم من الاستعلام الفرعي ثم يفحص العضوية فيها. ويصبح هذا الفرق مهمًا عند التعامل مع مجموعات داخلية كبيرة أو كثيرة التكرارات.
الاستعلام نفسه باستخدام IN
إليكم مكافئ استعلام العملاء الذين لديهم طلبات باستخدام IN. النتيجة متطابقة منطقيًا، لكن الآلية مختلفة: فالاستعلام الفرعي غير مرتبط وينتج قائمة من معرّفات العملاء التي يفحصها الاستعلام الخارجي.
غالبًا ما تنتج المُحسِّنات الحديثة الخطة نفسها — لكن عند استخدام جدول orders كبير وكثير التكرارات، قد يتفوق EXISTS لأنه يتوقف عند أول تطابق.
SELECT c.name
FROM customers c
WHERE c.id IN (
SELECT o.customer_id FROM orders o
);NOT EXISTS أفضل من NOT IN
هذه هي خلاصة الدرس كله. إن NOT EXISTS هو الطريقة الآمنة للتعبير عن عملية anti-join. وعلى خلاف NOT IN، لا يتعطل بسبب قيم NULL في الاستعلام الداخلي.
ويعثر بصورة موثوقة على كل عميل ليست لديه طلبات، حتى إذا كان orders.customer_id يحتوي على قيم NULL.
SELECT c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);لماذا يُعد NOT EXISTS آمنًا مع NULL
يسأل NOT EXISTS فقط: هل عثر الاستعلام الفرعي المرتبط على أي صف مطابق؟ — أي إنه سؤال واضح إجابته نعم أو لا. ولا تحقق قيمة NULL في customer_id الشرط o.customer_id = c.id، لذلك لا تطابق شيئًا ولا تفسد المنطق.
قارنوا ذلك بـ NOT IN، حيث تؤدي قيمة NULL في القائمة إلى UNKNOWN وإسقاط جميع الصفوف. ولهذا يفضل المحاورون ذوو الخبرة استخدام NOT EXISTS في عمليات anti-join.
متى يكون IN أفضل فعليًا
كونوا متوازنين — فليس IN أسوأ دائمًا. عندما يعيد الاستعلام الفرعي قائمة صغيرة وثابتة ومميزة، يكون IN واضحًا وسريعًا:
- حفنة من القيم الحرفية، أو جدول بحث صغير جدًا.
- استعلام غير مرتبط يستطيع المُحسِّن تشغيله مرة واحدة وتخزينه مؤقتًا.
الاستعلام أدناه اصطلاحي تمامًا؛ واللجوء إلى EXISTS هنا تعقيد زائد.
SELECT name
FROM products
WHERE category_id IN (
SELECT id FROM categories WHERE active = true
);الإجابة الحديثة الصادقة
تعيد المُحسِّنات الناضجة، مثل Postgres وSQL Server وMySQL الحديثة، كتابة IN وEXISTS كثيرًا في صورة خطة semi-join نفسها. لذلك يكون الأداء في عضوية القيم الإيجابية العادية متطابقًا غالبًا.
أما الفروق التي لا تزال مهمة:
NOT INمقابلNOT EXISTS— صحة النتائج عند وجود NULL، وهي مسألة حقيقية لا تتعلق بالسرعة فقط.- الجداول الداخلية الكبيرة جدًا أو التي لا تحتوي على فهارس — إذ يوقف EXISTS التنفيذ مبكرًا.
EXISTS مقابل JOIN للتحقق من الوجود
هناك صياغة أخرى يطرحها المحاورون: لماذا لا نستخدم JOIN فحسب؟ يمكن للربط الذي يتحقق من الوجود فقط أن يكرر الصفوف إذا احتوى الطرف الأيمن على تكرارات، مما يفرض استخدام DISTINCT. أما EXISTS فلا يكرر الصف الخارجي أبدًا.
لذلك يكون EXISTS أوضح من JOIN ... DISTINCT عند إجراء فحص وجود محض. استخدموا الربط عندما تحتاجون فعلًا إلى أعمدة من الجدول الآخر.
SELECT DISTINCT c.name
FROM customers c
JOIN orders o ON o.customer_id = c.id;الفهارس تحسم الأمر
لا تكتمل إجابة الأداء من دون ذكر الفهارس. ينفذ EXISTS المرتبط عملية البحث الداخلية لكل صف خارجي، ولذلك فإن وجود فهرس على العمود المرتبط — هنا orders(customer_id) — هو ما يجعله سريعًا.
إن ذكر عبارة "سأضيف فهرسًا إلى عمود الربط الذي يعتمد عليه ارتباط الاستعلام الفرعي" يحول الإجابة النظرية إلى إجابة عملية يحترمها المحاورون.
CREATE INDEX idx_orders_customer_id
ON orders (customer_id);عبارة جاهزة للمقابلة
قولوا: "إن EXISTS اختبار منطقي مرتبط يوقف التنفيذ عند أول صف مطابق، بينما يفحص IN العضوية في قائمة من القيم. وفي الفحوص الإيجابية، تنتج المُحسِّنات الحديثة غالبًا خطة semi-join نفسها. أما الفرق الحقيقي فهو بين NOT EXISTS وNOT IN: إذ إن NOT EXISTS آمن مع NULL، لذلك أفضله في عمليات anti-join — وأتأكد من فهرسة العمود المرتبط."
تحقق سريع
جوهر النقاش حول EXISTS مقابل IN.
مراجعة
حُسمت المقارنة بين EXISTS وIN:
- إن
EXISTSاختبار منطقي مرتبط يوقف التنفيذ عند أول صف مطابق؛ وقائمة الاختيار داخله غير مهمة. - يفحص
INالعضوية في مجموعة من القيم، وهو مناسب للقوائم الصغيرة والمميزة وغير المرتبطة. - في الفحوص الإيجابية، تختار المُحسِّنات الحديثة غالبًا خطة semi-join نفسها.
- فضّلوا
NOT EXISTSعلىNOT INفي عمليات anti-join — فهو آمن مع NULL. وفهرسوا العمود المرتبط.
وبذلك نختتم دورة التعمق في الاستعلامات الفرعية.
الأسئلة الشائعة
هل درس «أداء EXISTS مقابل IN» مجاني؟
نعم — نص درس «أداء EXISTS مقابل IN» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة SQL Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة SQL Interview Prep 4 دروس في المجموع.
ماذا ستتعلم في «أداء EXISTS مقابل IN»؟
متى يتوقف EXISTS مبكرًا ويتفوق على IN، وهو سؤال متكرر في مقابلات الخبراء تتمرن على SQL Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ SQL Interview Prep؟
لا تُشترط خبرة سابقة. SQL Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «أداء EXISTS مقابل IN»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس SQL Interview Prep هذا؟
نعم. كل درس في SQL Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الاستعلامات الفرعية العددية في SELECT وWHERE
- الاستعلامات الفرعية في عبارة FROM (الجداول المشتقة)
- الاستعلامات الفرعية باستخدام IN وANY وALL
- أداء EXISTS مقابل IN