تنتهي مهلة الاستعلام عند تنفيذه من الويب، ولكن بسرعة فائقة عند تنفيذه من SSMS

StackOverflow https://stackoverflow.com/questions/2248112

سؤال

أحاول تصحيح مصدر مهلة SQL في تطبيق ويب أحتفظ به.لدي الكود المصدري لرمز C#، لذلك أعرف بالضبط ما هو الكود الذي يتم تشغيله.لقد قمت بتصحيح أخطاء التطبيق وصولاً إلى السطر الذي ينفذ تعليمات SQL البرمجية التي انتهت مهلتها، وأشاهد الاستعلام قيد التشغيل في ملف تعريف SQL.

عند تنفيذ هذا الاستعلام من الويب، تنتهي مهلته بعد 30 ثانية.ومع ذلك، عندما أقوم بقص/لصق الاستعلام تمامًا كما هو معروض في ملف التعريف، ووضعه في SSMS وتشغيله، فإنه يعود على الفور تقريبًا.لقد تتبعت المشكلة إلى أن ARITHABORT تم ضبطه على OFF في الاتصال الذي يستخدمه الويب (أي، إذا قمت بإيقاف تشغيل ARITHABORT في جلسة SSMS، فإنه يعمل لفترة طويلة، وإذا قمت بتشغيله مرة أخرى، فسيتم تشغيله سريع جدا).ومع ذلك، عند قراءة وصف ARITHABORT، لا يبدو أنه ينطبق...أنا أقوم فقط باختيار بسيط، ولا يوجد أي إجراء حسابي على الإطلاق..مجرد صلة داخلية واحدة بشرط WHERE:

لماذا يسبب ARITHABORT OFF هذا السلوك في هذا السياق؟؟هل هناك أي طريقة يمكنني من خلالها تغيير إعداد ARITHABORT لهذا الاتصال من SSMS؟أنا أستخدم SQL Server 2008.

هل كانت مفيدة؟

المحلول

لذلك يرسل رمز C # الخاص بك استعلام مخصص SQL إلى SQL Server، باستخدام ما الطريقة؟ هل فكرت في استخدام إجراء مخزن؟ من المحتمل أن يضمن نفس الأداء (على الأقل في المحرك) بغض النظر عن من اتصل به.

لماذا ا؟ يعد إعداد Ariphabort أحد الأشياء التي ينظر فيها المحسن عند تحديد كيفية تنفيذ استفسارك (بشكل أكثر تحديدا، للحصول على خطة للمطابقة). من الممكن أن تكون الخطة في ذاكرة التخزين المؤقت نفس الإعداد مثل SSMS، لذلك يستخدم الخطة المخزنة مؤقتا، ولكن مع الإعداد المعاكس رمز C # يجبر رمز إعادة ترجمة (أو ربما تضرب حقا سيئ خطة في ذاكرة التخزين المؤقت)، والتي يمكن أن تؤذي بالتأكيد الأداء في كثير من الحالات.

إذا كنت تتصل بالفعل بإجراء مخزن (أنت لم تنشر استعلامك، على الرغم من أنني أعتقد أنك تهدف إلى)، فيمكنك تجربة إضافة الخيار (إعادة ترجمة) إلى الاستعلام المخزوني (أو الاستعلامات) في الإجراء المخزن. سيعني ذلك أن هذه التصريحات ستؤدي دائما إلى إعادة ترجمة، لكنها قد تمنع استخدام الخطة السيئة التي يبدو أنها تضربها. خيار آخر هو التأكد من أنه عند تجميع الإجراء المخزن، يتم تنفيذ الدفعة مع تعيين Arithabort على.

أخيرا، يبدو أنك تسأل كيف يمكنك تغيير إعداد Arithabort في SSMS. أعتقد أن ما تهدف إلى طرحه هو كيف يمكنك إجبار إعداد Arithabort في التعليمات البرمجية الخاصة بك. إذا قررت الاستمرار في إرسال SQL مخصص من تطبيق C # الخاص بك، فيمكنك إرسال أمر كإرسال نصي له عبارات متعددة مفصولة بواسطة نصف كولون، على سبيل المثال:

SET ARITHABORT ON; SELECT ...

لمزيد من المعلومات حول سبب حدوث هذه المشكلة، راجع مقال Erland Sommarskog الكبير:

نصائح أخرى

هذه الإجابة يتضمن طريقة لحل هذه المشكلة:

عن طريق تشغيل الأوامر التالية كمسؤول في قاعدة البيانات تعمل جميع الاستعلامات كما هو متوقع بغض النظر عن إعداد Arithabort.

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

تحديث

يبدو أن معظم الناس ينتهي بهم الأمر إلى حدوث هذه المشكلة نادرا جدا، والتقنية المذكورة أعلاه هي إصلاح لائق لمرة واحدة. ولكن إذا تعرض استعلام معين هذه المشكلة أكثر من مرة، فإن الحل أكثر طويلة الأجل لهذه المشكلة سيكون استخدام تلميحات الاستعلام مثل OPTIMIZE FOR و OPTION(Recompile), ، كما هو موضح في هذه المقالة.

لقد تلقيت هذه المشكلة عدة مرات من قبل ولكن إذا كان لديك إجراء مخزن مع نفس المشكلة، فإن إسقاط المسألة المخزنة في حل المشكلة.

انها تسمى المعلمة استنشاق. تحتاج دائما إلى تجميع المعلمات دائما في بروك المخزنة لتجنب هذه المشكلة في المستقبل.

أنا أفهم أن هذا قد لا يكون ما يريد المصطلح الأصلي ولكن قد يساعد شخصا مع نفس المشكلة.

في حالة استخدام إطار الكيان، يجب أن تدرك أن معلمات الاستعلام من أجل قيم السلسلة يتم إرسالها إلى قاعدة البيانات ك NVARCHAR افتراضيا، إذا تم كتابة عمود قاعدة البيانات للمقارنة Varchar، اعتمادا على توليفك، قد تتطلب خطة تنفيذ الاستعلام الخاصة بك خطوة "تحويل ضمنية"، ذلك يجبر فحص كامل. يمكنني تأكيد ذلك عن طريق البحث في خيار مراقبة قاعدة البيانات في خيار الاستفسارات باهظة الثمن، والذي يعرض خطة التنفيذ.

أخيرا، وهو شرح حول هذا السلوك في هذه المقالة:https://www.sqlskills.com/blogs/jonathan/implicites-confersions-that-cause-index-scans/

كان لدي نفس المشكلة وتم إصلاحها عن طريق إجراء تنفيذ "مع إعادة ترجمة". يمكنك أيضا محاولة استخدام المعلمة استنساخ. كانت مشكلاتي مرتبطة ب SQL ذاكرة التخزين المؤقت.

إذا كان بإمكانك تغيير التعليمات البرمجية الخاصة بك لإصلاح استنشاق المعلمات، فإن تحسين التلميح غير المعروف هو خيارك الأفضل.إذا لم تتمكن من تغيير التعليمات البرمجية الخاصة بك، فإن الخيار الأفضل هو exec sp_recompile 'name of proc' والذي سيجبر فقط proc المخزن على الحصول على خطة تنفيذ جديدة.سيكون لإسقاط عملية proc وإعادة إنشائها تأثير مماثل، ولكن قد يتسبب في حدوث أخطاء إذا حاول شخص ما تنفيذ عملية proc أثناء قيامك بإسقاطها.يقوم DBCC FREEPROCCACHE بإسقاط جميع خططك المخزنة مؤقتًا والتي يمكن أن تدمر نظامك بما في ذلك التسبب في الكثير من المهلات في بيئة إنتاج المعاملات الثقيلة.لا يعد إعداد arithabort حلاً للمشكلة ولكنه أداة مفيدة لاكتشاف ما إذا كان استنشاق المعلمات هو المشكلة أم لا.

لدي نفس المشكلة عند محاولة الاتصال SP من SMSS، استغرق الأمر 2 ثانية، بينما استغرق الأمر من Webapp (ASP.NET) حوالي 3 دقائق.

لقد جربت جميع الحلول المقترحة sp_recompile, DBCC FREEPROCCACHE و DBCC DROPCLEANBUFFERS ولكن لا شيء ثابت مشكلتي، ولكن عندما حاول المعلمة استنشاقها فعلت الخدعة، وعملت على ما يرام.

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