Nel mio ufficio, abbiamo una query che è piuttosto brutta, ma funziona abbastanza bene nella produzione e nell'ambiente di sviluppo (rispettivamente 20 secondi e 4 secondi). Tuttavia nel nostro ambiente di test ci vogliono oltre 4 ore. SQL2005 (+ ultime patch) è in esecuzione in produzione e sviluppo. SQL2008R2 è in esecuzione in fase di test.
Ho dato un'occhiata al Piano delle query e mostra che SQL2008R2 sta usando TempDB, tramite un Table Spool (lazy spool) per memorizzare le righe restituite dal server collegato. Il passaggio successivo mostra i loop annidati (anti-join semi sinistro) mentre consumano il 96,3% della query. La linea tra i due operatori è a 5.398 MB!
Il piano di query per SQL 2005 non mostra alcun utilizzo di tempdb e nessun utilizzo di Anti Anti Join sinistro.
Di seguito è riportato il codice igienizzato e l'esecuzione prevede il piano 2005 in alto, il 2008R2 in basso.
Cosa sta causando il drastico rallentamento e il cambiamento? Mi aspettavo di vedere un piano di esecuzione diverso, quindi non mi dà fastidio. Il drammatico rallentamento dei tempi di interrogazione è ciò che mi preoccupa.
Devo guardare l'hardware sottostante, dal momento che la versione 2008R2 utilizza tempdb devo dare un'occhiata a come ottimizzare l'utilizzo di quello?
C'è un modo migliore per scrivere la query?
Grazie per l'aiuto.
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 :: Eseguita la query da una diversa istanza SQL2005, praticamente lo stesso piano di esecuzione di "buono". Non sono ancora sicuro di come le due versioni 2005 funzionino meglio sul server collegato 2008R2, rispetto alle istanze 2008R2 rispetto alle istanze 2008R2.
Anche se non nego che il codice possa usare un po 'di lavoro, se il problema fosse il codice, non vedrei gli stessi piani di exec in tutte le mie prove? Indipendentemente dalla versione di SQL?
:: EDIT :: Ho applicato SP1 e CU3 a entrambe le istanze 2008R2, ancora nessun dado. Ho impostato specificamente la collocazione nel server collegato, senza dadi. Ho impostato specificamente le autorizzazioni del mio utente accs per essere amministratore di sistema su entrambi i casi, senza dadi. Ho anche ricordato i miei interni SQL Server 2008 e la risoluzione dei problemi, vedremo se riesco a rintracciarli in qualche modo.
Grazie a tutti per l'aiuto e i suggerimenti.
:: EDIT :: Ho apportato varie modifiche alle autorizzazioni al server collegato. Ho usato accessi SQL, accessi al dominio, ho utenti impersonati, ho usato l'opzione "sia fatta usando questo contesto di sicurezza". Ho creato utenti su entrambi i lati del server collegato che dispongono dei diritti di amministratore di sistema sul server. Non ho più idee.
Vorrei ancora sapere perché SQL2005 sta eseguendo la query in modo così drammaticamente diverso da SQL2008R2. Se la query fosse sbagliata, vedrei il tempo di esecuzione di 4+ ore su SQL2005 e SQL2008R2.