SQL Server Bağlantılı Sunucu performansı: Uzak sorgular neden bu kadar pahalı?


14

Bağlantılı Sunucular aracılığıyla bağlı iki veritabanı sunucum var. Her ikisi de SQL Server 2008R2 veritabanlarıdır ve bağlı sunucu bağlantısı, geçerli oturum açma güvenlik bağlamı kullanılarak normal bir "SQL Server" bağlantısı üzerinden yapılır. Bağlı sunucuların ikisi de aynı veri merkezindedir, bu nedenle bağlantı bir sorun olmamalıdır.

Sütunun hangi değerlerinin identifieruzaktan kullanılabilir olduğunu, ancak yerel olarak olmadığını denetlemek için aşağıdaki sorguyu kullanıyorum .

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

EXCEPT

SELECT DISTINCT
    identifier 
FROM LocalDb.schema.[TableName] 

Her iki tabloda da sütunda kümelenmemiş dizinler bulunur identifier. Yerel olarak yaklaşık 54 milyon sıra, sadece 54 uzaktan. Sorgu planına bakıldığında, yürütme süresinin% 70'i "uzak sorguyu yürütmeye" ayrılmıştır. Ayrıca, tam sorgu planını incelerken, 1bunun yerine tahmini yerel satır 2695380sayısı (yalnızca bundan sonra gelen sorguyu seçerken tahmini satır sayısı EXCEPT) olur. Yürütme planı Bu sorguyu yürütürken, gerçekten uzun zaman alıyor.

Merak ediyor: Neden bu? Tahmin "sadece" kapalı mı yoksa bağlantılı sunuculardaki uzak sorgular gerçekten pahalı mı?


2
BTW: Endeks arayışı için bakmanız gereken "tahmini yürütme sayısı" dır. Tahmini satır sayısı, yürütme başına, plan tam bir taramaya sahip olmadıkça tablonun satır sayısıyla ilişkili olmayan satır çıktısıdır.
Martin Smith

Yanıtlar:


9

Şu anda sahip olduğunuz plan benim için en uygun plan gibi görünüyor.

Diğer yanıtlardaki iddiayı, 2.6M satırlarını uzak sunucuya gönderdiğini kabul etmiyorum.

Plan bana uzak sorgudan döndürülen 54 satırın her biri için eşleşip eşleşmediğini belirlemek için yerel tablonuza bir dizin araması yapıyor gibi görünüyor. Bu hemen hemen en uygun plan.

Bir karma birleştirme veya birleştirme birleştirme ile değiştirmek, tablonun boyutu göz önüne alındığında verimsiz olur ve bir ara #temptablo eklemek , size herhangi bir avantaj sağlamayan ek bir adım ekler.


6

Uzak bir kaynağa bağlanmak pahalıdır. Dönemi.

Herhangi bir programlama ortamında en pahalı işlemlerden biri ağ IO'sudur (disk IO bunu cüce etme eğilimindedir).

Bu, uzak bağlantılı sunuculara kadar uzanır. Uzak bağlantılı sunucuyu çağıran sunucunun önce bir bağlantı kurması, ardından uzak sunucuda bir sorgu yürütülmesi, sonuçların döndürülmesi ve bağlantının kapatılması gerekir. Tüm bunlar ağ üzerinden zaman alır.


Ayrıca sorgunuzu, kablodaki minimum verileri aktaracak şekilde yapılandırmalısınız. DB'nin sizin için optimize etmesini beklemeyin.

Bu sorguyu yazacak olsaydım, uzak verileri bir tablo değişkenine (veya geçici tabloya) seçer ve bunu yerel tabloyla birlikte kullanırdım. Bu, yalnızca aktarılması gereken verilerin gönderilmesini sağlar.

Çalıştırdığınız sorgu, EXCEPTmaddeyi işlemek için uzak sunucuya kolayca 2.6M satırları gönderiyor olabilir .


Tamam, bu yüzden bağlantıyı kurmak için yüksek başlangıç ​​maliyetleri var. Sorgunun gönderilmesi, uzaktan işlenmesi (bunun için ağa gerek yoktur) ve son olarak sonuçların geri gönderilmesi ve işlenmesi gerekir. Ancak ağ bağlantısı üzerinden veri göndermek birkaç dakika sürmez, değil mi?
vstrien

@vstrien - Olabilir. Ağ bağlantısına, gecikmeye, doygunluğa ve diğer faktörlere bağlıdır. Nokta varlık - deterministik değildir.

@vstrien - Cevabıma daha fazla bilgi eklendi. Yazılan sorgu yerel satırları işleme için uzak sunucuya göndereceğini düşünüyorum.

2
2.6M satırlarını uzak sunucuya gönderdiği gerçeğini nereden çıkarıyorsunuz? Uzak sorgu operatörleri ile planları ile çok deneyimim yok ama 54 satır uzak sorgu operatörü geliyor gibi görünüyor sonra yerel tablo karşı anti yarı birleştirme yapıyor.
Martin Smith

2
@Lieven - Mantıksal olabilir, ancak gösterilen plandan doğru olduğunu düşünmeyin.
Martin Smith

1

Uzman değilim ama Union, Except veya Intersect kullanıyorsanız, "Distinct" kullanmanıza gerek yok. LocalDb.schema. [TableName] değerlerine bağlı olarak, sorgu performansı artırılabilir.

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

EXCEPT

SELECT 
    identifier 
FROM LocalDb.schema.[TableName]

0

Oded doğrudur, performans sorununa uzak sunucunuza 2.6M satırları gönderilir.

Bu sorunu gidermek için, geçici verileri veya bellek tablosundaki bir kullanarak uzak verilerin (54 satır) size gönderilmesini zorlayabilirsiniz.

Geçici bir tablo kullanma

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

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

DROP    #TableName

İç içe döngüler yalnızca 54 satır için makul görünse de, geçici bir tablo kullanmak her durumda kardinalite tahminlerine yardımcı olabilir.
Martin Smith

Geçici bir tablo kullanmak 54 satır ile çalışır; ancak her iki tarafta büyük masaların bulunduğu durumlarda artık mümkün değildir. Eşit büyüklükteki iki "dev" tablo için çözümünüz ne olurdu? Başka bir veritabanında bir UserTable oluşturma?
vstrien

1
@vstrien - Eşit büyüklükte iki büyük masa için gerçekten iyi bir çözüm yok. Dağıtılmış Bölünmüş Görünüm oluşturmak belki ilginizi çeker, ancak bununla ilgili hiçbir deneyimim yok.
Lieven Keersmaekers

0

Ben uzak tabloyu sorgudan sunucuya çoğaltma ve daha sonra tüm SQL yerel olarak çalışan daha iyi olduğunu düşünüyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.