it-swarm.asia

مشاكل أداء SQL مع الاستعلام عن بعد عبر الخادم المرتبط

هذا البقع

create proc dbo.Get_Accounts as
begin
  declare @current_date datetime
  set @current_date = dbo.fn_currdate()

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = @current_date
end

باستمرار يفشل بعد 10 دقائق برسالة الخطأ التالية:

الخادم: Msg 7399 ، المستوى 16 ، الحالة 1 ، السطر 1 OLE موفر DB 'SQLOLEDB' أبلغ عن خطأ. تم إنهاء التنفيذ بواسطة الموفر لأنه تم الوصول إلى حد الموارد. [موفر OLE/DB عاد message: انتهت المهلة] OLE تتبع خطأ قاعدة البيانات [ICommandText :: Execute 'SQLOLEDB' موفر OLE/DB أرجع 0x80040e31: تم إنهاء التنفيذ بواسطة الموفر لأنه تم الوصول إلى حد الموارد.].

ومع ذلك ، عندما أقوم بتشغيل نفس الاستعلام من نفس قاعدة البيانات (وليس على قاعدة البيانات البعيدة) في نافذة استعلام تفاعلية مع التاريخ الثابت:

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = '1/20/2012'

يعود في 30 ثانية.

الخادم المحلي هو SQLSERVER 2008 ، جهاز التحكم عن بعد هو SQLSERVER 2000.

لقد قمنا بما يلي دون جدوى:

  • إعادة إنشاء proc المخزنة.
  • sp_recompile على proc المخزنة
  • تحديث الإحصائيات على dbo.accounts
  • إسقاط وإعادة إنشاء الفهارس على dbo.accounts
  • انخفض المؤشر على dbo.accounts ومحاولة
  • DBCC FREEPROCCACHE & DBCC DROPCLEANBUFFERS على كل من الخوادم المحلية والبعيدة
  • إعادة تشغيل الخادم البعيد (ليس خيارًا سهلاً على الخادم المحلي)

الأسئلة

  • يمكن لأي شخص أن يفسر هذا السلوك الغريب؟
  • أي اقتراحات بشأن خيارات أخرى لتصحيحها؟
8
Bob Probst

يمكنك تشغيل إشارة التتبع 73 التي قد تمنحك رسالة خطأ أكثر تفصيلاً

كم عدد الصفوف التي يرجعها الاستعلام التمثيلي؟ ما مدى سرعة/موثوقية اتصال الشبكة بين الخادمين؟

من الممكن أن يستغرق نقل مجموعة البيانات الكبيرة وقتًا طويلاً (أعلى وقت الاستعلام الفعلي). يمكنك رفع قيمة المهلة.

يمكنك محاولة إعادة تكوين إعداد المهلة كما يلي:

اضبط مهلة تسجيل الدخول عن بُعد على 300 ثانية:

sp_configure 'remote login timeout', 300
go 
reconfigure with override 
go 

قم بتعيين مهلة الاستعلام البعيد إلى 0 (انتظار لانهائي):

sp_configure 'remote query timeout', 0 
go 
reconfigure with override 
go 

التحديث : SQL Server 2012 SP1 فصاعدًا : المستخدمون الذين لديهم SELECT سيتمكن الإذن من الوصول إلى DBCC SHOW_STATISTICS والذي سيحسن أداء القراءة فقط على الخوادم المرتبطة. المرجع: https://msdn.Microsoft.com/en-us/library/ms174384 (v = sql.110) .aspx

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

يمكنك أن ترى أن التقديرات مختلفة. عندما ركضت كمسؤول النظام ، كان التقدير صفًا واحدًا ، وهو رقم صحيح ، نظرًا لعدم وجود أوامر في Northwind حيث يتجاوز معرّف الطلب 20000. ولكن عندما أجريت كمستخدم عادي ، كان التقدير 249 صفًا. ندرك أن هذا الرقم بالذات هو 30٪ من 830 طلبًا ، أو تقديرًا لعملية عدم المساواة عندما لا يكون لدى المُحسن أي معلومات. سابقًا ، كان هذا بسبب قيمة متغيرة غير معروفة ، ولكن في هذه الحالة لا يوجد متغير يمكن أن يكون غير معروف. لا ، إن الإحصائيات نفسها هي المفقودة.

طالما أن الاستعلام يصل إلى الجداول فقط في الخادم المحلي ، يمكن للمحسن الوصول دائمًا إلى إحصائيات جميع الجداول في الاستعلام ؛ لا توجد عمليات فحص أذونات إضافية. ولكن هذا يختلف مع الجداول الموجودة على خادم مرتبط. عندما يصل SQL Server إلى خادم مرتبط ، لا يوجد بروتوكول سري يستخدم فقط للاتصال بين الخادم. لا ، بدلاً من ذلك يستخدم SQL Server المعيار OLE DB DB للخوادم المرتبطة ، ويكون مثيلات SQL Server أخرى ، أو Oracle ، أو ملفات نصية أو مصدر بياناتك المنزلي ، ويربط مثل أي مستخدم آخر. تعتمد كيفية استرداد الإحصائيات بالضبط على مصدر البيانات و OLE DB المعني. في هذه الحالة ، يكون الموفر هو SQL Server Native Client الذي يسترد الإحصائيات في خطوتين. (يمكنك مشاهدة هذا عن طريق تشغيل Profiler على الخادم البعيد). أولاً يقوم الموفر بتشغيل الإجراء sp_table_statistics2_rowset الذي يقوم بإرجاع معلومات حول إحصائيات العمود الموجودة ، بالإضافة إلى معلوماتها الأساسية وكثافتها. في الخطوة الثانية ، يقوم الموفر بتشغيل DBCC SHOW_STATISTICS ، وهو أمر التي تُرجع إحصائيات التوزيع الكاملة. (سنلقي نظرة أقرب على هذا الأمر لاحقًا في هذه المقالة.) في ما يلي الخطأ: لتشغيل SHOW_STATISTICS DBCC ، يجب أن تكون عضوًا في sysadmin لدور الخادم أو أي من أدوار قاعدة البيانات db_owner أو db_ddladm في.

ولهذا حصلت على نتائج مختلفة. عند تشغيل نظام مسؤول النظام ، حصلت على إحصائيات التوزيع الكاملة التي أشارت إلى عدم وجود صفوف بمعرف الطلب> 20000 ، وكان التقدير صفًا واحدًا. (تذكر أن المُحسِّن لا يفترض مطلقًا صفوفًا من الإحصاءات). ولكن عند التشغيل كمستخدم عادي ، فشل SHOW_STATISTICS DBCC مع وجود خطأ إذن. لم يتم نشر هذا الخطأ ، ولكن بدلاً من ذلك قبل المحسن أنه لا توجد إحصائيات واستخدم الافتراضات الافتراضية. نظرًا لأنها حصلت على معلومات أساسية ، فقد علمت أن الجدول البعيد يحتوي على 830 صفًا ، حيث يقدر بـ 249 صفًا.

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

  • يمكنك إضافة المستخدمين إلى الدور db_ddladmin ، ولكن بما أن هذا يمنحهم الحق في إضافة الجداول وإفلاتها ، فإن هذا غير مستحسن.

  • بشكل افتراضي ، عندما يتصل المستخدمون بخادم بعيد يتصلون بأنفسهم ، ولكن يمكنك إعداد تعيين تسجيل دخول باستخدام sp_addlinkedsrvlogin ، بحيث يتم تعيين المستخدمين لحساب وكيل له عضوية في db_ddladmin. لاحظ أن حساب الوكيل هذا يجب أن يكون تسجيل دخول SQL ، لذا لا يعد هذا خيارًا إذا لم يتم تمكين مصادقة SQL على الخادم البعيد. هذا الحل أيضًا مشكوك فيه إلى حد ما من منظور أمني ، على الرغم من أنه أفضل من الاقتراح السابق.

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

  • يمكنك بالطبع استخدام البطارية الكاملة للتلميحات وأدلة الخطة للحصول على الخطة التي تريدها.

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

11
Mitch Wheat

ماذا يحدث عند تجربة هذا (أي الإشارة صراحةً إلى ما يجب تشغيله على الخادم البعيد) ؟:

select [fields]
into dbo.current_accounts
from OPENQUERY(linkedserver, 'SELECT [fields] FROM database.dbo.accounts where date = ''1/20/2012''');

أشك في قضيتك أعلاه أن SQL Server يقوم فقط بسحب الجدول بأكمله من الخادم البعيد ثم تشغيل الاستعلام محليًا (لقد رأيت هذا يحدث عدة مرات في الماضي). أفضل أن أكون صريحًا (إما باستخدام OPENQUERY أو عن طريق إنشاء SP على الخادم البعيد) لذلك ليس هناك أي احتمال للتشويش.

2
Gareth

نظرًا لأن هذه مشكلة في مصدر الموارد ، فقد يكون تجمع الذاكرة خارج خادم SQL المستخدم لتحميل برامج التشغيل الخارجية وقد يكون CLR قريبًا من حده. القيمة الافتراضية هي 256 ميجابايت. للتغلب على هذا ، أقترح عليك الانتقال إلى مدير تكوين خادم SQL ، علامة تبويب متقدمة وإضافة الخيار -g إلى نهاية معلمات بدء التشغيل. i -e ؛ -g1024 ثم إعادة تشغيل خدمة SQL Server. أفعل ذلك عادةً لأننا نستخدم عددًا كبيرًا من الخوادم المرتبطة. http://msdn.Microsoft.com/en-us/library/ms190737.aspx

1
nopol

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

فكرتي الأولى هي تثبيت الإجراء المخزن في مربع SQL Server 2000 ، مع الإشارة إلى الخادم المحلي. يمكنك بعد ذلك تنفيذ الإجراء المخزن عن بعد.

exec linkedserver.database.dbo.Get_Accounts

إذا كان بإمكانك السير في هذا الطريق ، فمن المفترض أن يحسن الأداء بشكل كبير.

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

1
Jeff Siver