Методы ускорения огромного удаления из без предложений

dba.stackexchange https://dba.stackexchange.com/questions/1750

  •  16-10-2019
  •  | 
  •  

Вопрос

Использование SQL Server 2005.

Я выполняю огромный удаление, без каких -либо положений. Это в основном эквивалентно оператору таблицы усечения - за исключением того, что мне не разрешено использовать усечение. Проблема в том, что таблица огромна - 10 миллионов рядов, и для завершения затраты за час. Есть ли способ сделать это быстрее без:

  • Используя усечение
  • Отключение или отброшение индексов?

T-Log уже на отдельном диске.

Любые предложения приветствуются!

Это было полезно?

Решение

То, что вы можете сделать, это удаление партии, как это:

SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
    DELETE TOP (xxx) MyTable

Где XXX, скажем, 50000

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

SELECT col1, col2, ... INTO #Holdingtable
           FROM MyTable WHERE ..some condition..

SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
    DELETE TOP (xxx) MyTable WHERE ...

INSERT MyTable (col1, col2, ...)
           SELECT col1, col2, ... FROM #Holdingtable

Другие советы

Вы можете использовать верхний пункт, чтобы легко сделать это:

WHILE (1=1)
BEGIN
    DELETE TOP(1000) FROM table
    IF @@ROWCOUNT < 1 BREAK
END

Я согласен с предложениями о том, чтобы превратить ваши удаления в управляемые куски, если вы не можете использовать усечение, и мне нравится предложение Drop/Create для ее оригинальности, но мне любопытно по поводу следующего комментария в вашем вопросе:

Это в основном эквивалентно операции усечения таблицы - За исключением того, что мне не разрешено использовать усечение

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

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

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

Еще одним преимуществом использования хранимой процедуры таким образом является то, что сама хранящаяся процедура может быть заблокирована, чтобы использовать только конкретные учетные записи.

Если по какой -то причине это не является приемлемым решением, и вам необходимо удалить данные в этой таблице. в запланированное время каждый день.

Надеюсь это поможет!

За исключением усечения .. только удаление партий может помочь вам.

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

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

Запрос изменен из это дублировать вопрос. Кредит @Rlf для базы запросов.

CREATE TABLE #DelTest (ID INT IDENTITY, name NVARCHAR(128)); -- Build the test table
INSERT INTO #DelTest (name) SELECT name FROM sys.objects;  -- fill from system DB
SELECT COUNT(*) TableNamesContainingSys FROM #deltest WHERE name LIKE '%sys%'; -- check rowcount
go
DECLARE @HowMany INT;
DECLARE @RowsTouched INT;
DECLARE @TotalRowCount INT;
DECLARE @msg VARCHAR(100);
DECLARE @starttime DATETIME 
DECLARE @currenttime DATETIME 

SET @RowsTouched = 1; -- Needs to be >0 for loop to start
SET @TotalRowCount=0  -- Total rows deleted so far is 0
SET @HowMany = 5;     -- Variable to choose how many rows to delete per loop
SET @starttime=GETDATE()

WHILE @RowsTouched > 0
BEGIN
   DELETE TOP (@HowMany)
   FROM #DelTest 
   WHERE name LIKE '%sys%';

   SET @RowsTouched = @@ROWCOUNT; -- Rows deleted this loop
   SET @TotalRowCount = @TotalRowCount+@RowsTouched; -- Increment Total rows deleted count
   SET @currenttime = GETDATE();
   SELECT @msg='Deleted ' + CONVERT(VARCHAR(9),@TotalRowCount) + ' Records. Runtime so far is '+CONVERT(VARCHAR(30),DATEDIFF(MILLISECOND,@starttime,@currenttime))+' milliseconds.'
   RAISERROR(@msg, 0, 1) WITH NOWAIT;  -- Print message after every loop. Can't use the PRINT function as SQL buffers output in loops.  

END; 
SELECT COUNT(*) TableNamesContainingSys FROM #DelTest WHERE name LIKE '%sys%'; -- Check row count after loop finish
DROP TABLE #DelTest;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top