Пейджинг Вставка массива данных в таблицу

Может быть, это глупый вопрос, но как разделить/разбить на страницы вставку, чтобы другие операции обновляли ту же таблицу.

У меня есть две хранимые процедуры, одна из которых вставляет объемные данные.

Хранимая процедура InsertIntoMyTable:

INSERT INTO MyTable (column1, Column2, Column3)
SELECT Column1, @Column2, 0
FROM MyOtherTable

Первичный ключ MyTable(Column1, Column2)

А также есть операция MERGE с той же таблицей MyTable, но из другого источника, в основном с обновлением (столбец3), но также можно вставлять данные в MyTable.

Проблема в том, что когда вставка в MyTable занимает много времени, 10 миллионов записей, хранимая процедура, выполняющая MERGE, должна ждать, пока не завершится InsertIntoMyTable.

Пытаясь решить эту проблему, добавил разбитый на страницы

DECLARE @Start INT = 1
DECLARE @End INT = 1000
DECLARE @Amount INT = 1000
DECLARE @Total INT

SELECT @Total = COUNT(Column1) FROM MyOtherTable WHERE Column2 = @Column2

WHILE (@Start<=@Total)
BEGIN
   INSERT INTO MyTable (column1, Column2, Column3)
      SELECT Column1, @Column2, 0
      FROM (SELECT 
               Column1, 
               Row_number() OVER(ORDER BY Column1) rownumber 
            FROM MyOtherTable 
            WHERE Column2 = @Column2) x
      WHERE x.rownumber between @start and @end

   SET @start = @end+1
   SET @End = @End + @Amount
END

но по-прежнему блокирует таблицу до завершения операции.

Примечание. Выполнение не является транзакцией.


person Mariano G    schedule 17.09.2014    source источник


Ответы (1)


Выполнение ЯВЛЯЕТСЯ транзакцией. Если вы сами не предоставите явную транзакцию, SQL Server будет использовать неявную транзакцию.

И если у вас есть более 5000 операций (INSERT, DELETE, UPDATE) в одной транзакции, SQL Server снимет блокировки отдельных строк и вместо этого выполнит эскалацию блокировки и вместо этого монопольную блокировку вся таблица, поэтому никакие другие операции невозможны до тех пор, пока эта (возможно, неявная) транзакция не будет зафиксирована (или не будет отменена).

Часть, которая вставляется блоками по 1000 строк, не должна вызывать укрупнение блокировки, но, конечно, любые строки, которые вставляются в контексте этой транзакции, не могут быть одновременно прочитаны или обработаны другой транзакцией.

person marc_s    schedule 17.09.2014
comment
Я изменил свой код примерно так. WHILE (@Start‹=@Total) BEGIN BEGIN TRAN Вставка здесь... COMMIT TRAN END Но по-прежнему блокируется до вставки всех строк. - person Mariano G; 18.09.2014