Що є найбільш ефективним способом порівняння двох великих наборів результатів у SQL Server 2012


9

Поточна порада щодо найбільш ефективного способу порівняння двох великих наборів результатів / рядків, як видається, полягає у використанні EXCEPTоператора. Цей самодостатній сценарій SQL нижче стає дуже неефективним із збільшенням розмірів рядків (зміна значень @last). Я намагався знайти унікальні записи в комбінованій таблиці, але без вдосконалення.

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

Відповіді:


8

EXCEPTпередбачає DISTINCTоперацію.

Я б використав, NOT EXISTSякщо цього насправді не потрібно.

Однак проблема, яка виникає, швидше за все, ви отримуєте вкладені петлі в недекларовану таблицю через погані оцінки кардинальності, пов'язані зі змінними таблиці.

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

Ви зможете врахувати, що таблиці мають по 100 К рядків у кожній і дають інший план.

У SQL Server 2012 ви можете додавати індекси до змінних таблиць лише через обмеження. Якщо значення унікальні, ви можете використовувати

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

щоб додати індекс. Якщо зроблено в обох таблицях, план (після додавання підказки про перекомпіляцію), швидше за все, використовуватиме об'єднання об'єднань. Без жодних індексів я очікував би приєднання хешу.


Дякую, Мартіне. Це відповідь. ВАРІАНТ (РЕКОМПЛІЯЦІЯ) допоміг (100 000 за 5 хвилин), але УНІКАЛЬНЕ КЛАСТИРОВАНО на обох столах значно покращилось (100 000 за 7 секунд !!!). Я створив ці таблиці лише для того, щоб продемонструвати проблему реального життя, коли я не маю контролю над індексуванням таблиць на двох різних серверах SQL, але я буду керувати нею через такі змінні таблиці.
Буде Хілі

4
#tempТаблиці @WillHealey мають багато переваг перед змінними таблиць (статистика, паралелізм, більш гнучка індексація), тому якщо ви не використовуєте це в контексті, де ви обмежені табличними змінними, ви можете спробувати і їх.
Мартін Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.