سؤال

لقد قمت بإعادة بناء قسم بطيء من تطبيق ورثناه من شركة أخرى لاستخدام صلة داخلية بدلاً من استعلام فرعي مثل

where id in (select id from ... )

يعمل الاستعلام المُعاد هيكلته بشكل أسرع بنحو 100 مرة. (حوالي 50 ثانية إلى ~0.3) كنت أتوقع حدوث تحسن، ولكن هل يمكن لأي شخص أن يشرح لماذا كان هذا الأمر جذريًا للغاية؟تم فهرسة جميع الأعمدة المستخدمة في جملة حيث.هل يقوم SQL بتنفيذ الاستعلام في جملة المكان مرة واحدة لكل صف أو شيء من هذا القبيل؟

تحديث - شرح النتائج:

الفرق موجود في الجزء الثاني من استعلام "حيث المعرف في ()" -

2   DEPENDENT SUBQUERY  submission_tags ref st_tag_id   st_tag_id   4   const   2966    Using where

مقابل صف واحد مفهرس مع الصلة:

    SIMPLE  s   eq_ref  PRIMARY PRIMARY 4   newsladder_production.st.submission_id  1   Using index
هل كانت مفيدة؟

المحلول

سيتم تنفيذ "استعلام فرعي مرتبط" (أي استعلام تعتمد فيه الحالة على القيم التي تم الحصول عليها من صفوف الاستعلام المحتوي) مرة واحدة لكل صف.سيتم تنفيذ استعلام فرعي غير مرتبط (حيث يكون الشرط مستقلاً عن الاستعلام المحتوي) مرة واحدة في البداية.يقوم محرك SQL بهذا التمييز تلقائيًا.

لكن، نعم، شرح الخطة سيعطيك التفاصيل القذرة.

نصائح أخرى

أنت تقوم بتشغيل الاستعلام الفرعي مرة واحدة لكل صف بينما يحدث الانضمام على الفهارس.

وهنا مثال على كيفية ذلك يتم تقييم الاستعلامات الفرعية في MySQL 6.0.

سيقوم المحسن الجديد بتحويل هذا النوع من الاستعلامات الفرعية إلى صلات.

قم بتشغيل خطة الشرح على كل إصدار، وسوف يخبرك بالسبب.

قبل تشغيل الاستعلامات على مجموعة البيانات، يتم وضعها من خلال مُحسِّن الاستعلام، ويحاول المُحسِّن تنظيم الاستعلام بطريقة تمكنه من إزالة أكبر عدد ممكن من الصفوف (الصفوف) من مجموعة النتائج بأسرع ما يمكن.في كثير من الأحيان، عند استخدام الاستعلامات الفرعية (خاصة السيئة منها)، لا يمكن اقتطاع المجموعات من مجموعة النتائج حتى يبدأ تشغيل الاستعلام الخارجي.

بدون رؤية الاستعلام، من الصعب تحديد ما هو السيء جدًا في النص الأصلي، ولكن أعتقد أنه كان شيئًا لم يتمكن المُحسِّن من تحسينه كثيرًا.سيؤدي تشغيل "شرح" إلى إظهار طريقة أدوات التحسين لاسترداد البيانات.

عادةً ما يكون ذلك نتيجة لعدم تمكن المُحسِّن من معرفة أنه يمكن تنفيذ الاستعلام الفرعي كصلة وفي هذه الحالة يقوم بتنفيذ الاستعلام الفرعي لكل سجل في الجدول بدلاً من ربط الجدول في الاستعلام الفرعي مقابل الجدول الذي تستعلم عنه.بعض قواعد البيانات "المؤسسية" أفضل في هذا الأمر، لكنها ما زالت تفوتها في بعض الأحيان.

هذا السؤال عام إلى حد ما، فإليك الإجابة العامة:

في الأساس، تستغرق الاستعلامات وقتًا أطول عندما يكون لدى MySQL الكثير من الصفوف التي يمكن فرزها.

افعل هذا:

قم بتشغيل شرح لكل استعلام (الاستعلام المنضم، ثم الاستعلام الفرعي)، وانشر النتائج هنا.

أعتقد أن رؤية الاختلاف في تفسير MySQL لهذه الاستعلامات سيكون بمثابة تجربة تعليمية للجميع.

يجب أن يقوم الاستعلام الفرعي بتشغيل استعلام واحد لكل صف تم إرجاعه.يجب على الصلة الداخلية فقط تشغيل استعلام واحد.

انظر إلى خطة الاستعلام لكل استعلام.

حيث و ينضم يستطيع عادة سيتم تنفيذها باستخدام نفس خطة التنفيذ، لذلك عادة لا يوجد أي سرعة للتغيير بينهما.

لم يقم المُحسِّن بعمل جيد جدًا.عادة يمكن تحويلها دون أي فرق ويمكن للمحسن القيام بذلك.

من المحتمل أن الاستعلام الفرعي كان ينفذ "فحصًا كاملاً للجدول".بمعنى آخر، عدم استخدام الفهرس وإرجاع عدد كبير جدًا من الصفوف التي يحتاج الاستعلام الرئيسي إلى تصفيتها.

مجرد تخمين دون تفاصيل بالطبع ولكن هذا هو الوضع الشائع.

باستخدام الاستعلام الفرعي، يتعين عليك إعادة تنفيذ التحديد الثاني لكل نتيجة، وعادةً ما يُرجع كل تنفيذ صفًا واحدًا.

من خلال الصلة، يقوم التحديد الثاني بإرجاع عدد أكبر من الصفوف، ولكن عليك تنفيذه مرة واحدة فقط.الميزة هي أنه يمكنك الآن ضم النتائج، وضم العلاقات هو ما يفترض أن تكون قاعدة البيانات جيدة فيه.على سبيل المثال، ربما يتمكن المُحسِّن من اكتشاف كيفية الاستفادة بشكل أفضل من الفهرس الآن.

إنه ليس استعلامًا فرعيًا بقدر ما هو عبارة IN، على الرغم من أن الصلات هي أساس محرك SQL الخاص بـ Oracle على الأقل وتعمل بسرعة كبيرة.

منقول من الدليل المرجعي (14.2.10.11 إعادة كتابة الاستعلامات الفرعية كصلات):

يمكن أن تكون الصلة اليسرى [الخارجية] أسرع من استعلام فرعي مكافئ لأن الخادم قد يكون قادرًا على تحسينها بشكل أفضل - وهي حقيقة لا تقتصر على MySQL Server وحده.

لذلك يمكن أن تكون الاستعلامات الفرعية أبطأ من LEFT [OUTER] JOINS.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top