Qual è il modo più efficiente per confrontare due grandi set di risultati in SQL Server 2012


9

La consulenza attuale per il modo più efficiente di confrontare due grandi set di risultati / righe sembra essere quella di utilizzare l' EXCEPToperatore. Questo script SQL autonomo di seguito diventa molto inefficiente all'aumentare delle dimensioni delle righe (modifica dei valori @last). Ho provato a trovare voci uniche in una tabella combinata ma senza alcun miglioramento.

DECLARE @first AS INT, @step AS INT, @last AS INT; 

-- This script is comparing two record sets using EXCEPT
-- I want to find additions from OLD to NEW
-- As number of rows increase performance gets terrible
-- I don't have to use two tables. I could use one combined table but I want the same result as quickly as possible

-- Compare 100 to 110 rows - 0 seconds
-- Compare 1000 to 1010 rows - 1 seconds
-- Compare 10000 to 10010 rows - 16 seconds
-- Compare 100000 to 100010 rows - ABORT after 8 minutes (tables are populated in 18 seconds)

DECLARE @temptableOLD TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100000
WHILE(@first <= @last) BEGIN INSERT INTO @temptableOLD VALUES(@first) SET @first += @step END

DECLARE @temptableNEW TABLE ([Result1] int);
SET @step = 1;  SET @first = 1; SET @last = 100010
WHILE(@first <= @last) BEGIN INSERT INTO @temptableNEW VALUES(@first) SET @first += @step END

select * from @temptableNEW
except
select * from @temptableOLD

Risposte:


8

EXCEPTimplica DISTINCTun'operazione.

Vorrei utilizzare NOT EXISTSse questo non è effettivamente richiesto.

Tuttavia, è probabile che si stia riscontrando cicli annidati su una tabella non indicizzata a causa delle stime di cardinalità scadenti associate alle variabili della tabella.

select * from @temptableNEW
except
select * from @temptableOLD
OPTION (RECOMPILE)

Sarà in grado di tenere conto del fatto che le tabelle hanno 100K righe ciascuna e fornire un piano diverso.

In SQL Server 2012 è possibile aggiungere solo indici alle variabili di tabella tramite vincoli. Se i valori sono univoci è possibile utilizzare

DECLARE @temptableOLD TABLE ([Result1] int UNIQUE CLUSTERED);

per aggiungere un indice. Se eseguito su entrambe le tabelle, il piano (dopo aver aggiunto il suggerimento di ricompilazione) utilizzerà probabilmente un join di unione. Senza alcun indice mi aspetterei un hash join.


Grazie Martin. Questa è la risposta OPTION (RECOMPILE) ha aiutato (100.000 in 5 minuti), ma UNICO CLUSTER su entrambi i tavoli ha fatto il grande miglioramento (100.000 in 7 secondi !!!). Ho creato solo queste tabelle per dimostrare un problema di vita reale in cui non ho alcun controllo sull'indicizzazione delle tabelle su due diversi server SQL, ma lo gestirò attraverso tali variabili di tabella.
Will Healey,

4
Le #temptabelle di @WillHealey hanno molti vantaggi rispetto alle variabili di tabella (statistiche, parallelismo, indicizzazione più flessibile), quindi se non lo si utilizza in un contesto in cui si è limitati alle variabili di tabella, è possibile provare anche queste.
Martin Smith,
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.