Leistung von SQL Server-Verbindungsservern: Warum sind Remoteabfragen so teuer?


13

Ich habe zwei Datenbankserver, die über Verbindungsserver verbunden sind. Bei beiden handelt es sich um SQL Server 2008R2-Datenbanken, und die Verbindung zum Verbindungsserver wird über eine reguläre "SQL Server" -Verbindung hergestellt, wobei der Sicherheitskontext des aktuellen Logins verwendet wird. Die Verbindungsserver befinden sich beide im selben Rechenzentrum, sodass die Verbindung kein Problem darstellen sollte.

Ich benutze die folgende Abfrage, um zu überprüfen, welche Werte der Spalte identifierremote, aber nicht lokal verfügbar sind.

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

EXCEPT

SELECT DISTINCT
    identifier 
FROM LocalDb.schema.[TableName] 

In beiden Tabellen befinden sich nicht gruppierte Indizes für die Spalte identifier. Lokal sind es etwa 2,6 Millionen Zeilen, nur im Remote-Zugriff 54. Bei Betrachtung des Abfrageplans werden jedoch 70% der Ausführungszeit für "Ausführen von Remote-Abfragen" verwendet. Beim Studium des vollständigen Abfrageplans wird 1stattdessen die Anzahl der geschätzten lokalen Zeilen angegeben 2695380(dies ist die Anzahl der geschätzten Zeilen, wenn nur die nachfolgende Abfrage ausgewählt wird EXCEPT). Ausführungsplan Die Ausführung dieser Abfrage dauert in der Tat sehr lange.

Ich frage mich: Warum ist das so? Ist die Schätzung "nur" weg oder sind Remote-Abfragen auf Verbindungsservern wirklich so teuer?


2
Übrigens: Es ist die "geschätzte Anzahl von Ausführungen", die Sie für die Indexsuche betrachten sollten. Die geschätzte Anzahl der Zeilen ist die Anzahl der pro Ausführung ausgegebenen Zeilen, die sich nicht auf die Anzahl der Zeilen in der Tabelle selbst bezieht, es sei denn, der Plan enthält einen vollständigen Scan.
Martin Smith

Antworten:


9

Der Plan, den Sie im Moment haben, scheint mir der optimalste zu sein.

Ich bin mit der Behauptung in den anderen Antworten nicht einverstanden, dass es die 2.6M Reihen zum Fernbediener sendet.

Der Plan sieht für mich so aus, als würde für jede der 54 von der Remote-Abfrage zurückgegebenen Zeilen eine Indexsuche in Ihrer lokalen Tabelle durchgeführt, um festzustellen, ob eine Übereinstimmung vorliegt oder nicht. Dies ist so ziemlich der optimale Plan.

Das Ersetzen durch einen Hash-Join oder einen Merge-Join wäre angesichts der Größe der Tabelle kontraproduktiv, und das Hinzufügen einer Zwischentabelle #tempfügt lediglich einen zusätzlichen Schritt hinzu, der Ihnen keinen Vorteil zu bringen scheint.


6

Das Herstellen einer Verbindung zu einer Remote-Ressource ist teuer. Zeitraum.

Eine der teuersten Operationen in jeder Programmierumgebung ist die Netzwerk-E / A (obwohl die Festplatten-E / A dazu neigt, sie in den Schatten zu stellen).

Dies gilt auch für Remote-Verbindungsserver. Der Server, der den Remote-Verbindungsserver aufruft, muss zuerst eine Verbindung herstellen. Anschließend muss eine Abfrage auf dem Remote-Server ausgeführt, die Ergebnisse zurückgegeben und die Verbindung geschlossen werden. Dies alles braucht Zeit über das Netzwerk.


Sie sollten Ihre Abfrage auch so strukturieren, dass Sie die minimalen Daten über die Leitung übertragen. Erwarten Sie nicht, dass die DB für Sie optimiert.

Wenn ich diese Abfrage schreiben würde, würde ich die entfernten Daten in eine Tabellenvariable (oder in eine temporäre Tabelle) auswählen und diese dann in Verbindung mit der lokalen Tabelle verwenden. Dies stellt sicher, dass nur Daten übertragen werden, die übertragen werden müssen.

Die Abfrage, die Sie ausführen, kann problemlos 2.6M Zeilen an den Remote-Server senden, um die EXCEPTKlausel zu verarbeiten .


Ok, so hat es hohe Startkosten, um die Verbindung aufzubauen. Die Abfrage muss gesendet, remote verarbeitet (kein Netzwerk erforderlich) und schließlich die Ergebnisse zurückgesendet und verarbeitet werden. Aber es wird nicht Minuten dauern, um Daten über eine Netzwerkverbindung zu senden, oder?
Vstrien

@ Vstrien - Es könnte. Abhängig von der Netzwerkverbindung, der Latenz, der Sättigung und anderen Faktoren. Point being - es ist nicht deterministisch.

@ vstrien - Weitere Informationen in meiner Antwort hinzugefügt. Ich glaube, dass die Abfrage, wie sie geschrieben wurde, die lokalen Zeilen zur Verarbeitung an den Remote-Server sendet.

2
Woher ziehen Sie die Schlussfolgerung, dass die 2.6M-Zeilen an den Remoteserver gesendet werden? Ich habe nicht viel Erfahrung mit Plänen mit Remote-Abfrageoperatoren, aber es sieht so aus, als ob die 54 Zeilen aus dem Remote-Abfrageoperator stammen, dann wird der Antisemit-Join für die lokale Tabelle ausgeführt.
Martin Smith

2
@Lieven - Könnte logisch sein, aber denke nicht, dass es aus dem gezeigten Plan richtig ist.
Martin Smith

1

Ich bin kein Experte, aber wenn Sie Union, Except oder Intersect verwenden, müssen Sie "Distinct" nicht verwenden. Abhängig von den Werten aus LocalDb.schema. [TableName] kann die Abfrageleistung verbessert werden.

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

EXCEPT

SELECT 
    identifier 
FROM LocalDb.schema.[TableName]

0

Oded ist richtig, das Leistungsproblem wird durch das Senden der 2.6M-Zeilen an Ihren Remote-Server verursacht.

Um dieses Problem zu beheben, können Sie das Senden der Remote-Daten (54 Zeilen) erzwingen, indem Sie eine temporäre oder eine In-Memory-Tabelle verwenden.

Temporäre Tabelle verwenden

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

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

DROP    #TableName

Die Verwendung einer temporären Tabelle kann in jedem Fall bei Kardinalitätsschätzungen hilfreich sein, obwohl eine verschachtelte Schleife nur für 54 Zeilen sinnvoll erscheint.
Martin Smith

Die Verwendung einer temporären Tabelle funktioniert mit 54 Zeilen. aber in fällen mit großen tischen auf beiden seiten ist das nicht mehr machbar. Was wäre Ihre Lösung für zwei gleich große "riesige" Tische? Erstellen einer UserTable in einer anderen Datenbank?
Vstrien

1
@vstrien - für zwei gleich große große Tische gibt es keine wirklich gute Lösung. Vielleicht ist das Erstellen einer verteilten partitionierten Ansicht für Sie von Interesse, aber ich habe keinerlei Erfahrung damit.
Lieven Keersmaekers

0

Ich denke, Sie sind besser dran, die entfernte Tabelle auf den Server zu replizieren, den Sie abfragen, und dann all Ihre SQL-Anweisungen lokal auszuführen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.