it-swarm.asia

أداء SQL Server Linked Server: لماذا الاستعلامات البعيدة مكلفة للغاية؟

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

أستخدم الاستعلام التالي للتحقق من قيم العمود identifier المتوفرة عن بعد ، ولكن ليس محليًا.

SELECT 
    identifier 
FROM LinkedServer.RemoteDb.schema.[TableName]

EXCEPT

SELECT DISTINCT
    identifier 
FROM LocalDb.schema.[TableName] 

على كلا الجدولين توجد فهارس غير مجمعة في العمود identifier. يوجد حوالي 2.6 مليون صف محليًا ، عن بُعد 54 فقط. ومع ذلك ، عند النظر في خطة الاستعلام ، يتم تخصيص 70٪ من وقت التنفيذ لـ "تنفيذ الاستعلام عن بُعد". أيضًا ، عند دراسة خطة الاستعلام الكاملة ، يكون عدد الصفوف المحلية المقدرة 1 بدلا من 2695380 (وهو عدد الصفوف المقدرة عند تحديد الاستعلام بعد EXCEPT) فقط. Execution plan عند تنفيذ هذا الاستعلام ، يستغرق الأمر وقتًا طويلاً بالفعل.

يجعلني أتساءل: لماذا هذا؟ هل التقدير "فقط" بعيد المنال ، أم أن الاستعلامات البعيدة على الخوادم المرتبطة مكلفة حقًا؟

15
vstrien

الخطة التي لديك في الوقت الحالي تبدو أفضل خطة لي.

لا أتفق مع التأكيد الوارد في الإجابات الأخرى على أنه يرسل صفوف 2.6M إلى الخادم البعيد.

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

الاستبدال بعلاقة تجزئة أو دمج الدمج سيؤدي إلى نتائج عكسية بالنظر إلى حجم الجدول وإضافة وسيط #temp يضيف الجدول خطوة إضافية فقط لا يبدو أنها تمنحك أي ميزة.

10
Martin Smith

الاتصال بمورد بعيد مكلف. فترة.

واحدة من أغلى العمليات في أي بيئة برمجة هي الشبكة IO (على الرغم من أن القرص IO يميل إلى تقزمه).

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


يجب عليك أيضًا بناء الاستعلام الخاص بك بطريقة تنقل الحد الأدنى من البيانات عبر السلك. لا تتوقع أن يحسن DB لك.

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

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

6
Oded

أنا لست خبيراً ولكن إذا كنت تستخدم Union ، باستثناء ، أو Intersect ، فليس عليك استخدام "Distinct". بناءً على القيم من LocalDb.schema. [TableName] ، يمكن تحسين أداء الاستعلام.

SELECT 
    identifier 
FROM LinkedServer.RemoteDb.schema.[TableName]

EXCEPT

SELECT 
    identifier 
FROM LocalDb.schema.[TableName]
1
joakon

إن Oded صحيح ، وتحدث مشكلة الأداء عن طريق إرسال صفوف 2.6M إلى خادمك البعيد.

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

باستخدام جدول مؤقت

SELECT  identifier 
INTO    #TableName
FROM    LinkedServer.RemoteDb.schema.[TableName]

SELECT  identifier
FROM    #TableName
EXCEPT
SELECT  DISTINCT identifier 
FROM    LocalDb.schema.[TableName] 

DROP    #TableName
0
Lieven Keersmaekers

أعتقد أنه من الأفضل لك نسخ الجدول البعيد إلى الخادم الذي تستعلم منه ثم تشغيل كل SQL محليًا.

0
Alen