Prestazioni di SQL Server Linked Server: perché le query remote sono così costose?


14

Ho due server di database, collegati tramite server collegati. Entrambi sono database SQL Server 2008R2 e la connessione al server collegato viene stabilita tramite un normale link "SQL Server", utilizzando il contesto di sicurezza dell'account di accesso corrente. I server collegati sono entrambi nello stesso datacenter, quindi la connessione non dovrebbe essere un problema.

Uso la seguente query per verificare quali valori della colonna identifiersono disponibili in remoto, ma non localmente.

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

EXCEPT

SELECT DISTINCT
    identifier 
FROM LocalDb.schema.[TableName] 

Su entrambe le tabelle sono presenti indici non cluster sulla colonna identifier. A livello locale sono circa 2,6 milioni di righe, solo 54 in remoto. Tuttavia, quando si esamina il piano di query, il 70% del tempo di esecuzione è dedicato all'esecuzione di query remote. Inoltre, quando si studia il piano di query completo, il numero di righe locali stimate è 1invece di 2695380(che è il numero di righe stimate quando si seleziona solo la query successiva EXCEPT). Progetto esecutivo Quando si esegue questa query, ci vuole davvero molto tempo.

Mi chiedo: perché è questo? La stima è "appena" lontana o le query remote su server collegati sono davvero così costose?


2
A proposito: è il "numero stimato di esecuzioni" che dovresti cercare per la ricerca dell'indice. Il numero stimato di righe è l'output delle righe per esecuzione che non sarà correlato al numero di righe nella tabella stessa a meno che il piano non abbia una scansione completa.
Martin Smith,

Risposte:


9

Il piano che hai al momento sembra il piano più ottimale per me.

Non sono d'accordo con l'affermazione nelle altre risposte che sta inviando le righe 2.6M al server remoto.

Il piano mi sembra come se per ognuna delle 54 righe restituite dalla query remota stia eseguendo una ricerca dell'indice nella tabella locale per determinare se è abbinata o meno. Questo è praticamente il piano ottimale.

Sostituire con un hash join o unire join sarebbe controproducente date le dimensioni della tabella e l'aggiunta di una #temptabella intermedia aggiunge solo un passaggio aggiuntivo che sembra non darti alcun vantaggio.


6

La connessione a una risorsa remota è costosa. Periodo.

Una delle operazioni più costose in qualsiasi ambiente di programmazione è l'IO di rete (anche se l'IO del disco tende a ridurlo).

Questo si estende ai server collegati remoti. Il server che chiama il server collegato remoto deve prima stabilire una connessione, quindi è necessario eseguire una query sul server remoto, restituire i risultati e chiudere la connessione. Tutto ciò richiede tempo sulla rete.


Dovresti anche strutturare la tua query in modo tale da trasferire i dati minimi attraverso il filo. Non aspettarti che il DB si ottimizzi per te.

Se dovessi scrivere questa query, selezionerei i dati remoti in una variabile di tabella (o in una tabella temporanea) e quindi li utilizzerei insieme alla tabella locale. Ciò garantisce che lo faranno solo i dati che devono essere trasferiti.

La query che stai eseguendo può facilmente inviare 2.6M righe al server remoto per elaborare la EXCEPTclausola.


Ok, quindi ha alti costi di avvio per impostare la connessione. La query deve essere inviata, elaborata in remoto (non è necessaria alcuna rete per quella) e infine i risultati restituiti ed elaborati. Ma non ci vorranno minuti per inviare dati tramite una connessione di rete, vero?
vstrien,

@vstrien - Potrebbe. Dipende dalla connessione di rete, dalla latenza, dalla saturazione e da altri fattori. Il punto è che non è deterministico.

@vstrien - Aggiunte ulteriori informazioni nella mia risposta. Credo che la query scritta invierà le righe locali al server remoto per l'elaborazione.

2
Da dove deduci il fatto che sta inviando le righe 2.6M al server remoto? Non ho molta esperienza con i piani con gli operatori di query remoti, ma sembra che le 54 righe escano dall'operatore di query remoto, quindi sta facendo l'anti semi join rispetto alla tabella locale.
Martin Smith,

2
@Lieven - Potrebbe essere logico ma non pensare che sia corretto dal piano mostrato.
Martin Smith,

1

Non sono un esperto, ma se si utilizza Union, Except o Intersect, non è necessario utilizzare "Distinct". A seconda dei valori di LocalDb.schema. [TableName], è possibile migliorare le prestazioni della query.

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

EXCEPT

SELECT 
    identifier 
FROM LocalDb.schema.[TableName]

0

Oded ha ragione, il problema delle prestazioni è causato dall'invio delle righe 2.6M al server remoto.

Per risolvere questo problema, è possibile forzare l'invio dei dati remoti (54 righe) utilizzando una tabella temporanea o in memoria.

Utilizzando una tabella temporanea

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

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

DROP    #TableName

L'utilizzo di una tabella temporanea potrebbe aiutare in ogni caso con le stime della cardinalità, sebbene un ciclo annidato sembri ragionevole per sole 54 righe.
Martin Smith,

L'uso di una tabella temporanea funziona correttamente con 54 righe; ma nei casi con tavoli di grandi dimensioni su entrambi i lati non è più possibile. Quale sarebbe la tua soluzione per due "enormi" tavoli di uguali dimensioni? Creazione di una tabella utente in un altro database?
vstrien,

1
@vstrien - non c'è davvero una buona soluzione per due enormi tavoli uguali. Forse la creazione di una vista partizionata distribuita ti interessa, ma non ne ho alcuna esperienza.
Lieven Keersmaekers,

0

Penso che sia meglio replicare la tabella remota sul server da cui si esegue la query e quindi eseguire tutto il proprio SQL localmente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.