Jaki jest najbardziej efektywny sposób porównania dwóch dużych zestawów wyników w programie SQL Server 2012


9

Bieżącą radą dotyczącą najbardziej efektywnego sposobu porównywania dwóch dużych zestawów wyników / wierszy wydaje się być użycie EXCEPToperatora. Ten samodzielny skrypt SQL poniżej staje się bardzo nieefektywny wraz ze wzrostem rozmiarów wierszy (zmiana wartości @last). Próbowałem znaleźć unikalne wpisy w połączonej tabeli, ale bez poprawy.

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

Odpowiedzi:


8

EXCEPToznacza DISTINCToperację.

Użyłbym, NOT EXISTSjeśli nie jest to faktycznie wymagane.

Jednak problem, który masz, prawdopodobnie powoduje zagnieżdżenie pętli w nieindeksowanej tabeli ze względu na słabe oszacowania liczności związane ze zmiennymi tabeli.

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

Będzie mógł wziąć pod uwagę, że tabele mają 100 000 wierszy każdy i podać inny plan.

W SQL Server 2012 można dodawać indeksy do zmiennych tabeli tylko poprzez ograniczenia. Jeśli wartości są unikalne, możesz użyć

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

aby dodać indeks. Jeśli zostanie to wykonane w obu tabelach, plan (po dodaniu wskazówki dotyczącej ponownej kompilacji) prawdopodobnie zamiast tego użyje połączenia scalającego. Bez indeksów oczekiwałbym przyłączenia mieszającego.


Dziękuję Martin. Oto odpowiedź. Pomogła OPCJA (RECOMPILE) (100 000 w 5 minut), ale WYJĄTKOWE ZESTAWIENIE na obu stołach znacznie poprawiło (100 000 w 7 sekund !!!). Te tabele utworzyłem tylko w celu zademonstrowania rzeczywistego problemu, w którym nie mam kontroli nad indeksowaniem tabel na dwóch różnych serwerach SQL, ale będę zarządzał nimi za pomocą takich zmiennych tabeli.
Will Healey,

4
#tempTabele @WillHealey mają wiele zalet w porównaniu ze zmiennymi tabelowymi (statystyki, równoległość, bardziej elastyczne indeksowanie), więc jeśli nie używasz tego w kontekście ograniczonym do zmiennych tabel, możesz również spróbować tych zmiennych.
Martin Smith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.