In meinem Büro haben wir eine Abfrage, die ziemlich hässlich ist, aber in der Produktion und in der Entwicklungsumgebung (20 Sekunden bzw. 4 Sekunden) ziemlich gut läuft. In unserer Testumgebung dauert es jedoch mehr als 4 Stunden. SQL2005 (+ neueste Patches) wird in Produktion und Entwicklung ausgeführt. SQL2008R2 wird getestet.
Ich habe mir den Abfrageplan angesehen und er zeigt, dass SQL2008R2 TempDB über einen Table Spool (Lazy Spool) verwendet, um die zurückgegebenen Zeilen vom Verbindungsserver zu speichern. Der nächste Schritt besteht darin, dass verschachtelte Schleifen (linker Anti-Semi-Join) 96,3% der Abfrage verschlingen. Die Leitung zwischen den beiden Betreibern liegt bei 5.398 MB!
Der Abfrageplan für SQL 2005 zeigt keine Verwendung von Tempdb und keine Verwendung eines Left Anti Semi Join.
Unten finden Sie den bereinigten Code und die Ausführungspläne für den Plan 2005 oben und den Plan 2008R2 unten.
Was verursacht die drastische Verlangsamung und Veränderung? Ich hatte erwartet, einen anderen Ausführungsplan zu sehen, was mich also nicht stört. Die dramatische Verlangsamung der Abfragezeit macht mir Sorgen.
Muss ich mir die zugrunde liegende Hardware ansehen, da die 2008R2-Version Tempdb verwendet, muss ich mir ansehen, wie ich die Nutzung dieser Hardware optimieren kann?
Gibt es eine bessere Möglichkeit, die Abfrage zu schreiben?
Danke für die Hilfe.
INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT
Table1.iGroupID,
GETDATE()
FROM Table1
WHERE
NOT EXISTS (
SELECT 1
FROM LinkedServer.Database.Table2 Alias2
WHERE
(
Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
AND NOT Alias2.FirstName IS NULL
AND NOT Alias2.LastName IS NULL
) OR (
Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
AND NOT Alias2.Familyname IS NULL
AND NOT Alias2.Child1Name IS NULL
) OR (
Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
AND NOT Alias2.StepFamilyName IS NULL
AND NOT Alias2.StepFamilyNameChild1 IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
)
) AND NOT EXISTS (
SELECT 1
FROM Table3
INNER JOIN Table4
ON Table4.FirstNameType = Table3.FirstNameType
INNER JOIN table5
ON table5.LastNameType = Table3.LastNameType
WHERE
Table3.iGroupID = Table1.iGroupID
AND Table3.bIsClosed = 0
AND Table4.sNameTypeConstant = 'new_lastname'
AND table5.sFirstNameConstant = 'new_firstname'
)
:: EDIT :: Die Abfrage wurde von einer anderen SQL2005-Instanz ausgeführt, so ziemlich dem gleichen Ausführungsplan wie der "gute". Ich bin mir immer noch nicht sicher, wie die beiden 2005-Versionen auf dem 2008R2-Verbindungsserver besser ausgeführt werden als die 2008R2-Instanzen auf den 2008R2-Instanzen.
Ich leugne zwar nicht, dass der Code etwas Arbeit gebrauchen könnte, aber wenn der Code das Problem wäre, würde ich dann nicht in allen meinen Versuchen die gleichen Exec-Pläne sehen? Unabhängig von der SQL-Version?
:: EDIT :: Ich habe SP1 und CU3 auf beide 2008R2-Instanzen angewendet, immer noch keine Würfel. Ich habe speziell die Kollokation im Verbindungsserver festgelegt, keine Würfel. Ich habe speziell festgelegt, dass die Berechtigungen meines Benutzerkontos in beiden Fällen sysadmin sind, keine Würfel. Ich habe mich auch an meine SQL Server 2008-Interna und die Fehlerbehebung erinnert. Wir werden sehen, ob ich dies irgendwie nachverfolgen kann.
Vielen Dank an alle für die Hilfe und die Tipps.
:: EDIT :: Ich habe verschiedene Berechtigungsänderungen am Verbindungsserver vorgenommen. Ich habe SQL-Anmeldungen und Domänenanmeldungen verwendet. Ich habe mich als Benutzer ausgegeben. Ich habe die Option "Mit diesem Sicherheitskontext erstellt werden" verwendet. Ich habe Benutzer auf beiden Seiten des Verbindungsservers erstellt, die über Systemadministratorrechte auf dem Server verfügen. Ich habe keine Ideen mehr.
Ich würde immer noch gerne wissen, warum SQL2005 die Abfrage so dramatisch von SQL2008R2 unterscheidet. Wenn die Abfrage fehlerhaft wäre, würde die Laufzeit von 4+ Stunden sowohl auf SQL2005 als auch auf SQL2008R2 angezeigt.
quelle
+1 beim Versuch, Ihren Abfragekommentar vom Datagod umzuschreiben.
Ich frage mich auch, ob Sie auf der Seite des Verbindungsservers auf ein Berechtigungsproblem stoßen, das zu dieser Verlangsamung führt. Ich habe vor einiger Zeit über diese Verlangsamung des Verbindungsservers gebloggt. Möglicherweise lohnt es sich, die Dauerwellen zu überprüfen (handelt es sich um einen SQL-Verbindungsserver? Oder um ein anderes DBMS? Wenn letzteres der Fall ist, erhalten Sie ohnehin keine hervorragenden Statistiken).
Haben Sie SQL Server 2005 in der Testumgebung noch, um diese Abfrage anzuprobieren und die Umgebung auszuschließen?
Haben Sie die Statistiken seit dem Upgrade neu erstellt?
quelle
Es gibt so viele Probleme mit diesem Vergleich ... Ich weiß nur nicht, wo ich anfangen soll.
Holen Sie sich die genauen Spezifikationen für Ihre Produktions- und Testmaschinen.
Bestimmen Sie die Netzwerkverbindungen zwischen den verschiedenen verbundenen Servern in beiden Umgebungen. Sind sie gleich schnell? Befinden sich die Server in beiden Umgebungen nebeneinander?
Gibt es überhaupt eine Möglichkeit, die Abfrage neu zu schreiben, um KEINE Verbindungsserver zu verwenden? Wenn Sie Tabellen über mehrere Server hinweg verbinden, sind Sie anfällig für Topologieänderungen und in den meisten Fällen fürchterlich langsam.
Die Verwendung von NOT und OR führt normalerweise zu vollständigen Tabellenscans. Versuchen Sie, die Abfrage neu zu schreiben.
quelle