1 - Использовать дозирование. Это позволяет вам возобновить и дать вам представление о прогрессе. В качестве примера:
, что я также добавил
WITH (TABLOCKX)
подсказку, что ставит блокировку таблицы, и исключает блокировку на уровне строк
DECLARE @MSG Varchar(max)
WHILE 1=1
BEGIN
DELETE TOP (100000) qvalues
FROM qvalues WITH (TABLOCKX)
<logic here>
IF @@ROWCOUNT < 100000 BREAK
SET @Msg = 'Deleted another 10 Million'
SET @Msg = @Msg + ' ' +CONVERT(varchar(20),GETDATE(),101)+' '+CONVERT(varchar(20),GETDATE(),108)
RAISERROR(@Msg, 0, 1) WITH NOWAIT
END
Примечание. Это вызовет проблемы с одновременным чтением, но, надеюсь, у вас нет ничего другого, запрашивающего эту таблицу во время удаления.
2 - Исправьте логику Это невозможно написать для вас без лучшей идеей вашей структуры таблицы, но некоторые варианты: - Материализовать таблицу со значениями, которые вы хотите сравнить против и сделать соединение. Если удаление достаточно велико, вы можете сделать кластеризованный индекс в таблице temp в поле объединения. Я использовал это с большим успехом. - Если вы ожидаете удалить большую часть записей, SELECT INTO
новый стол и оставьте старый. Это минимально зарегистрированная операция и выполняется очень быстро на SQL Server 2008 по сравнению с удалением, для чего необходимо регистрировать значения для каждой строки. - Отбросьте все свои индексы, но то, что вы используете для выбора, и ваш кластеризованный индекс. Сохранение кластерного индекса обычно нормально для удаления этого типа, если это соответствующий кластер для запроса.
Вы уверены, что его 20 часов? Перед выполнением запроса убедитесь, что в таблице нет блокировки ... –
Есть ли указатель на таблице? Ключи? Схема? – jzd
@madh как проверить, есть ли блокировка –