2013-05-14 3 views
1

Я довольно новичок в SQL и базах данных в целом. Я использую SQL Server 2008 Mgmt Studio.TSQL while loop to merge

Я читал, что использование основанных на множестве операций лучше, чем RBAR (только что узнал, что сегодня!).

Вскоре я покажу вам два эквивалентных (я думаю) запросов, и я пытаюсь посмотреть, что больше эффективно.

Первая попытка:

DECLARE @persID int 
DECLARE @mag float 
DECLARE @temp TABLE (pID int PRIMARY KEY) 

INSERT INTO @temp 
SELECT persID FROM Person 

WHILE (SELECT COUNT(pID) FROM @temp) > 0 
BEGIN 
    SELECT TOP 1 @persID = pID FROM @temp  
    SELECT @mag = SQRT(SUM(value*value)) FROM PersonWord 
     WHERE PersonWord.persID = @persID 

    UPDATE Person 
    SET magnitude = @mag 
     WHERE persID = @persID 
    DELETE @temp WHERE pID = @persID 
END 

Вторая попытка:

DECLARE @temp TABLE (pID int PRIMARY KEY, mag float) 

INSERT INTO @temp 
    SELECT persID, SQRT(SUM(value*value)) FROM PersonWord 
     GROUP BY persID 

MERGE INTO Person AS p 
USING @temp AS t 
    ON p.persID = t.pID 
WHEN MATCHED 
THEN UPDATE 
    SET magnitude = t.mag 

Они сохраняются в виде хранимых процедур и предполагаемый план выполнения при запуске:

exec FirstAttempt 
exec SecondAttempt 

показывает 32% партии для FirstAttempt и 68% для SecondAttempt

Таблица PersonWord содержит около 41 миллионов записей ... Person таблица содержит примерно 170000

Любые мысли/советы будут приветствовать. Спасибо, что нашли время, я знаю, как могут быть неприятные вопросы newb (используемые для математической помощи Yahoo).

EDIT ::

работает на тех, кто PersonWord имея около 1,3 миллиона записей и Лицо, около 3000 ... версия со слиянием взял ~ 1,3 секунды для выполнения. Версия с циклом while составляла 6 минут, и она выполнила только 15% работы.

Для такого рода вещей, не основанных на RBAR!

+0

Вы видели расчетные планы выполнения и можете получить фактические планы выполнения. У вас есть вопрос, подходящий для StackOverflow? – HABO

+0

В Sql Server Mgt Studio щелкните правой кнопкой мыши запрос и выберите «включить статистику клиента», затем выполните каждый запрос в полтора десятка раз или около того. Вы получите дополнительную вкладку на выходе с информацией о времени. «Процент партии» для меня не был полезной метрикой. –

+0

@HABO да, для тех из вас, кто знает входы и выходы sql, является слиянием лучше, чем цикл while? я был здесь 2 дня, пытаясь найти ответ, только чтобы получить противоречивые результаты. – sylk

ответ

3

Никогда не используйте переменную таблицы для этого количества записей. Они предназначены для небольших наборов данных. Вместо этого используйте временную таблицу и проиндексируйте ее. Также я лично хотел бы найти способ ограничить количество записей, которые вы обновляете. Я не уверен, почему вы все равно используете слияние, поскольку это простое обновление. Код ниже должен работать.

Update P 
set SET magnitude = t.mag 
from Person AS p 
join #temp AS t 
    ON p.persID = t.pID 
WHERE magnitude <> t.mag 

И в зависимости от того, как часто вы собираетесь сделать это, я хотел бы попытаться сохранить этот расчет, так что нужно только произойдет один раз для каждой записи (и использовать rtigger, чтобы обновлять его, если изменение значений): SQRT (SUM (значение * значение))

BTW это плохая практика для плавания для любых математических вычислений, вы вводите ошибки округления, так как это не точно.

+0

Спасибо, HLGEM, я перешел на использование темповой таблицы на них. Эта и другие подобные процедуры не будут использоваться очень часто, возможно, 4 раза в год. Кроме того, точное значение магнетика не обязательно, округление даже при 10^-6 не повлияет на назначение значения магния. Я использовал Merge, потому что я читал, что это было в основном Update ... От, но мне нравится ваше решение, поскольку я более четко вижу, что происходит. – sylk

+0

MERGE - это слово TSQL для «Upsert». Aka, есть «что делать, когда у вас есть соответствие» и «что делать, когда вы не имеете соответствия» (в источнике или получателе). Если вы знаете, что у вас будут «совпадения», используйте «Обновить» (как уже было предложено). – granadaCoder

+0

http://en.wikipedia.org/wiki/Merge_(SQL) – granadaCoder