2016-10-03 2 views
1

Что является наиболее эффективным способом обновления таблицы на сервере sql, чтобы поставить лимит в 10 000 записей за одну транзакцию?Обновление Sql в партиях

Я прочитал о верхнем и ROWCOUNT подходах, добавив его в цикл while. Что из них более эффективно? Или, пожалуйста, поделитесь, если вы знаете альтернативные эффективные способы. Спасибо.

+0

Какой скрипт вы используете в настоящий момент? – mfredy

+0

НЕ используйте ROWCOUNT для управления тем, как строки будут обновляться с помощью инструкции UPDATE. Это использование для этого устарело и перестанет работать в будущем. https://msdn.microsoft.com/en-us/library/ms188774.aspx –

+0

Является ли ваше намерение обновлять каждую строку 10 000 за раз или всего лишь 10 000 строк? – ZLK

ответ

0

Вот один из возможных подходов без использования set rowcount

-- prepare test data 
use tempdb 
drop table dbo.t; 
create table dbo.t (a int identity, b int) 
go 
insert into dbo.t (b) 
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); 
go 

-- assume we do 3 records per time, put 10000 here if you wnat 10K records 
-- also the update is just to update column [b] to [b] * 2, here is the code 

declare @N int = 3; -- do a batch of @N records 

declare @i int = 0, @max_loop int; 

select @max_loop = count(*)/@N from dbo.t 

-- the first batch may include records <= @N-1 and the last batch may include records <= @N 
while (@i <= @max_loop) 
begin 

    ; with c as (
    select rnk=ROW_NUMBER() over (order by a)/@N, a, b from dbo.t 
    ) 
    update c set b = b*2 -- doule b 
    where rnk = @i; 

    set @i = @i + 1; 
end 
go 
-- check the result 
select * from dbo.t 
-1

Вы можете попробовать ниже подход:

WHILE (1=1) 
BEGIN 
    BEGIN TRANSACTION 
    UPDATE TOP (10000) XXX 
    SET XXX.YYY = <ValueToUpdate> 
    FROM XXX -- Update 10000 nonupdated rows 
    WHERE <condition> -- make sure that condition makes sure that it does not become infinite loop 
    IF @@ROWCOUNT = 0 
    BEGIN 
     COMMIT TRANSACTION 
     BREAK 
    END 
    COMMIT TRANSACTION 
END 

EDIT

Обновление для всех сотрудников организации и решений что он не станет петлей infinte. Здесь я обновляю modifiedDate для записи сотрудника.

DECLARE @updatedids table(id int) 
WHILE (1=1) 
BEGIN 
    BEGIN TRANSACTION 
    UPDATE TOP(10000) a  
    SET a.ModifiedDate = GETDATE() 
    OUTPUT inserted.BusinessEntityID INTO @updatedids 
    FROM HumanResources.Employee a 
LEFT JOIN @updatedids u 
    ON a.BusinessEntityID = u.id 
    WHERE u.id IS NULL 
    -- Update 10000 nonupdated rows 
    IF @@ROWCOUNT = 0 
    BEGIN 
     COMMIT TRANSACTION 
     BREAK 
    END 
    COMMIT TRANSACTION 
END 
+0

Это будет мертвый цикл, потому что те же 10000 строк могут обновляться непрерывно. (По крайней мере, в sql-сервере, который я тестировал) – jyao

+0

Я пропустил предложение WHERE. Сожалею. Я обновил код. В основном я сосредоточен на логике. –

+0

Для обновления GENERIC в таблице иногда может не существовать допустимое условие для фильтрации уже обновленных. Например, скажем, у нас есть таблица с двумя столбцами, [emploee_id] и [зарплата], также, скажем так, теперь мы хотим дать 10% увеличению для всех людей, и предположим, что эта таблица имеет 1 миллион строк, мы хотим обновить эту таблицу в обновлении 10K/chunk, как мы можем придумать хорошее предложение where? – jyao