سؤال

تحديث:يبدو أن الاستعلام لا يطرح أي مهلة.انتهت مهلة الاتصال.

هذا نموذج للتعليمات البرمجية لتنفيذ الاستعلام.في بعض الأحيان، أثناء تنفيذ الاستعلامات التي تستغرق وقتًا طويلاً، فإنها تؤدي إلى استثناء المهلة.

أنا لا تستطيع استخدم أيًا من هذه التقنيات:1) زيادة المهلة.2) تشغيله بشكل غير متزامن مع رد الاتصال.هذا يحتاج إلى تشغيل بطريقة متزامنة.

يرجى اقتراح أي تقنيات أخرى لإبقاء الاتصال حيًا أثناء تنفيذ استعلام يستغرق وقتًا طويلاً؟

private static void CreateCommand(string queryString,
    string connectionString)
{
    using (SqlConnection connection = new SqlConnection(
               connectionString))
    {
        SqlCommand command = new SqlCommand(queryString, connection);
        command.Connection.Open();
        command.ExecuteNonQuery();
    }
}
هل كانت مفيدة؟

المحلول

نظرًا لأنك تستخدم ExecuteNonQuery الذي لا يُرجع أي صفوف، فيمكنك تجربة هذا الأسلوب القائم على الاستقصاء.ينفذ الاستعلام بطريقة ASYC (بدون رد اتصال) ولكن التطبيق سوف ينتظر (داخل حلقة من حين لآخر) حتى يكتمل الاستعلام.من MSDN.هذا يجب أن يحل مشكلة المهلة.يرجى تجربتها.

لكنني أتفق مع الآخرين على أنه يجب عليك التفكير أكثر في تحسين الاستعلام بحيث يتم تنفيذه في أقل من 30 ثانية.

        IAsyncResult result = command.BeginExecuteNonQuery();

        int count = 0;
        while (!result.IsCompleted)
        {
            Console.WriteLine("Waiting ({0})", count++);
            System.Threading.Thread.Sleep(1000);
        }
        Console.WriteLine("Command complete. Affected {0} rows.",
        command.EndExecuteNonQuery(result));

نصائح أخرى

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

يجب أن أتفق مع Terrapin.

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

إذا لم يكن هذا خيارًا، أو إذا كنت تريد تجربة بعض الأشياء الأخرى أولاً، فإليك خياراتك الرئيسية الثلاثة:

  1. قم بتقسيم الاستعلام إلى مكونات تعمل ضمن المهلة المحددة.ربما هذا هو الأسهل.
  2. قم بتغيير الاستعلام لتحسين مسار الوصول من خلال قاعدة البيانات (بشكل عام:ضرب الفهرس بأقرب ما يمكن)
  3. قم بتغيير الفهارس أو إضافتها للتأثير على مسار الوصول لاستعلامك.

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

  1. تحقق من صحة DBA الخاص بك ومراجعة التعليمات البرمجية الأخرى التي قمت بالفعل بتحسين الاستعلام بأفضل شكل ممكن
  2. اعمل على بنية قاعدة البيانات الأساسية لمعرفة ما إذا كان هناك أي مكاسب يمكنك الحصول عليها من جانب قاعدة البيانات، من خلال إنشاء/تعديل فهرس (فهارس).
  3. قم بتقسيمها إلى أجزاء متعددة، حتى لو كان هذا يعني تشغيل الإجراءات باستخدام معلمات إرجاع متعددة تستدعي معلمة أخرى.(هذا الخيار ليس أنيقًا، وبصراحة، إذا كانت التعليمات البرمجية الخاصة بك ستستغرق الكثير من الوقت حقًا، فسأذهب إلى الإدارة وأعيد مناقشة المهلة البالغة 30 ثانية)

لقد واجهنا مؤخرًا مشكلة مماثلة في قاعدة بيانات SQL Server 2000.

أثناء الاستعلام، قم بتشغيل هذا الاستعلام على قاعدة البيانات الرئيسية الخاصة بك على خادم قاعدة البيانات ومعرفة ما إذا كان هناك أي أقفال يجب عليك استكشاف أخطاءها وإصلاحها:

select 
  spid,
  db_name(sp.dbid) as DBname,
  blocked as BlockedBy,
  waittime as WaitInMs,
  lastwaittype,
  waitresource,
  cpu,
  physical_io,
  memusage,
  loginame,
  login_time,
  last_batch,
  hostname,
  sql_handle
from sysprocesses sp
where (waittype > 0 and spid > 49) or spid in (select blocked from sysprocesses where blocked > 0)

يحتوي SQL Server Management Studio 2008 أيضًا على أداة مراقبة نشاط رائعة جدًا تتيح لك رؤية صحة قاعدة البيانات الخاصة بك أثناء الاستعلام.

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

إذا كان محظورًا عليك استخدام ميزات واجهة برمجة التطبيقات للوصول إلى البيانات للسماح للاستعلام بالاستمرار لأكثر من 30 ثانية، فسنحتاج إلى رؤية SQL.

تعتبر مكاسب الأداء التي سيتم تحقيقها من خلال تحسين استخدام ADO.NET طفيفة مقارنة بمكاسب تحسين SQL.

وأنت تستخدم بالفعل الطريقة الأكثر فعالية لتنفيذ SQL.ستكون التقنيات الأخرى أبطأ بشكل مذهل (على الرغم من أنك إذا قمت باسترجاع سريع لصفوفك وبعض المعالجة البطيئة جدًا من جانب العميل باستخدام DataSets، فقد تتمكن من تقليل وقت الاسترجاع الأولي إلى أقل من 30 ثانية، لكنني أشك في ذلك). )

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

يعد هذا اختراقًا قبيحًا، ولكنه قد يساعد في حل مشكلتك مؤقتًا حتى تتمكن من حل المشكلة الحقيقية

    private static void CreateCommand(string queryString,string connectionString)
    {
        int maxRetries = 3;
        int retries = 0;
        while(true)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    SqlCommand command = new SqlCommand(queryString, connection);
                    command.Connection.Open();
                    command.ExecuteNonQuery();
                }
                break;
            }
            catch (SqlException se)
            {
                if (se.Message.IndexOf("Timeout", StringComparison.InvariantCultureIgnoreCase) == -1)
                    throw; //not a timeout

                if (retries >= maxRetries)
                    throw new Exception( String.Format("Timedout {0} Times", retries),se);

                //or break to throw no error

                retries++;
            }
        }
    }
command.CommandTimeout *= 2;

سيؤدي ذلك إلى مضاعفة المهلة الافتراضية، وهي 30 ثانية.

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

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

إذا لم تتمكن مطلقًا من زيادة المهلة، فإن خيارك الوحيد هو تقليل وقت تنفيذ الاستعلام خلال المهلة الافتراضية البالغة 30 ثانية.

أميل إلى عدم الإعجاب بزيادة مهلة الاتصال/الأمر لأنه في رأيي سيكون الأمر يتعلق بالعناية بالأعراض، وليس المشكلة

هل فكرت في تقسيم الاستعلام إلى عدة أجزاء أصغر؟

أيضًا، هل قمت بتشغيل الاستعلام الخاص بك على Database Engine Tuning Advisor في:

ستوديو الإدارة > الأدوات > مستشار ضبط محرك قاعدة البيانات

وأخيرًا، هل يمكننا إلقاء نظرة على الاستعلام نفسه؟

هتافات

هل حاولت تغليف SQL الخاص بك داخل إجراء مخزن، يبدو أن لديهم إدارة أفضل للذاكرة.لقد رأيت مهلات مثل هذه من قبل في بيان SQL للخطة مع الاستعلامات الداخلية باستخدام ADO الكلاسيكي.أي.حدد * من (حدد ....) t الانضمام الداخلي إلى somthingTable.حيث كان الاستعلام الداخلي يعيد عدداً كبيراً جداً من النتائج.

نصائح أخرى 1.إجراء عمليات القراءة باستخدام تلميح التنفيذ باستخدام (nolock)، إنه أمر قذر ولا أوصي به ولكنه يميل إلى أن يكون أسرع.2.انظر أيضًا إلى خطة تنفيذ SQL التي تحاول تشغيلها وتقليل مسح الصفوف، والترتيب الذي تقوم به بضم الجداول.3.انظر إلى إضافة بعض الفهارس إلى جداولك لقراءة أسرع.4.لقد وجدت أيضًا أن حذف الصفوف أمر مكلف للغاية، ويمكنك محاولة تحديد عدد الصفوف لكل مكالمة.5.لقد نجح تبديل متغيراتtable مع الجداول #temporary أيضًا في الماضي.6.ربما تكون قد حفظت أيضًا خطة تنفيذ سيئة (سمعتها، ولم تشاهدها من قبل).

أتمنى أن يساعدك هذا

تحديث:يبدو أن الاستعلام لا يرمي أي مهلة.الاتصال هو التوقيت خارج.

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

قد يكون من المفيد محاولة ترحيل النتائج مرة أخرى.

فقط قم بتعيين خاصية CommandTimeout الخاصة بـ sqlcommand إلى 0، سيؤدي ذلك إلى انتظار الأمر حتى انتهاء الاستعلام ...على سبيل المثال:

SqlCommand cmd = new SqlCommand(spName,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top