Query di sintonia - SQL Server
-
16-10-2019 - |
Domanda
Uno dei nostri sviluppatori stanno cercando di eseguire il sotto query su un server di sviluppo, che coinvolge tirando i dati da un server collegato, la produzione. La query ha funzionato per più di 14 ore prima di essere fermato.
ho guardato il piano di esecuzione in SQL Sentry Plan Explorer - si prega di trovare il piano di esecuzione di seguito.
Come può questa query essere sintonizzato per migliorare le prestazioni? Ci sono errori evidenti nella query? Ci sono dei puntatori, blog post che mi aiuterà a migliorare questa ricerca?
Entrambi i server coinvolti sono SQL Server 2005
SELECT A.SETID
,A.CUST_ID
,A.CNTCT_SEQ_NUM
,A.NAME1
,A.TITLE
,C.DESCR
FROM PS_CUST_CONTACT A
,[linksrv].[prodDB].dbo.PS_BO_ROLE Z
,[linksrv].[prodDB].dbo.PS_RD_PERSON B
,[linksrv].[prodDB].dbo.PS_BO_ROLE_TYPE C
WHERE Z.BO_ID = B.BO_ID
AND Z.ROLE_TYPE_ID = C.ROLE_TYPE_ID
AND Z.ROLE_END_DT >= GETDATE()
AND A.EFFDT = (
SELECT MAX(EFFDT)
FROM PS_CUST_CONTACT CUST_CONTACT
WHERE CUST_CONTACT.SETID = A.SETID
AND CUST_CONTACT.CUST_ID = A.CUST_ID
AND CUST_CONTACT.CNTCT_SEQ_NUM = A.CNTCT_SEQ_NUM
AND CUST_CONTACT.EFFDT <= { FN CURDATE() }
)
AND A.EFF_STATUS = 'A'
AND B.PERSON_ID IN (
SELECT A1.PERSON_ID
FROM PS_CONTACT A1
,PS_CONTACT_CUST B1
WHERE A1.EFFDT = (
SELECT MAX(A_ED.EFFDT)
FROM PS_CONTACT A_ED
WHERE A1.SETID = A_ED.SETID
AND A1.CONTACT_ID = A_ED.CONTACT_ID
AND A_ED.EFFDT <= SUBSTRING(CONVERT(CHAR, GETDATE(), 121), 1, 10)
)
AND A1.SETID = B1.SETID
AND A1.CONTACT_ID = B1.CONTACT_ID
AND B1.EFFDT = (
SELECT MAX(B_ED.EFFDT)
FROM PS_CONTACT_CUST B_ED
WHERE B1.SETID = B_ED.SETID
AND B1.CONTACT_ID = B_ED.CONTACT_ID
AND B_ED.EFFDT <= A.EFFDT
)
AND A.CNTCT_SEQ_NUM = B1.CNTCT_SEQ_NUM
AND A.SETID = B1.CUSTOMER_SETID
AND A.CUST_ID = B1.CUST_ID
)
Soluzione
Per la carne che cosa Aaron afferma un po 'di più, le prestazioni del server collegato, in particolare per i grandi set di risultati, per il cross-server di join e subquery cross-server, è spesso deludente. Se si guarda il server remoto con Profiler, si potrebbe scoprire che il server locale bombarda il server remoto con le richieste per il recupero di una singola riga per abbinare unirsi colonne. Quando ciò accade, la latenza di rete e chiamando cospirare in testa per uccidere le prestazioni.
Se è possibile interrogare i dati locali senza troppi problemi, che sarebbe meglio. Potreste essere in grado di ripristinare un backup di produzione o utilizzare SSIS (o anche BCP, funziona ancora) per copiare i dati dal server di produzione ad alcuni tavoli di lavoro sul server locale. In generale SSIS, BCP e tattiche simili sono più veloce di server collegati e può aiutare ad evitare problemi con la crescita del file di registro.
Se è necessario interrogare i dati da un server remoto, è possibile che riscrivere la query in modo che utilizzi OPENQUERY () (nomi, piuttosto che quattro parti) e 'invia' tutte le 'parti remote' della query sopra al server remoto e quindi si unisce i risultati di tale ai dati locali saranno più efficaci. SQL dovrebbe essere abbastanza intelligente per spostare tutti i join al server remoto, ma a volte non e OPENQUERY () ti dà un metodo per forzare SQL per fare vuoi che si desidera.
Un altro, simile, tattica sarebbe quella di eseguire la 'parte remota' della query prima e mettere i risultati in una tabella temporanea, (opzionalmente) Indice tabella temporanea e poi unire la 'parte locale' della query al tabella temporanea. Ancora una volta, questo aiuta di forzare SQL per fare quello che dovrebbe.
Sembra più lavoro, ma SQL può essere in grado di comportarsi in modo più efficiente. Come sempre, guardare i tuoi tipi di dati sulla giunture e le tue SARGs o gli indici saranno ignorati.