Удалить инструкцию в SQL очень медленно



у меня есть такие заявления, которые тайм-аут:



DELETE FROM [table] WHERE [COL] IN ( '1', '2', '6', '12', '24', '7', '3', '5')


Я пробовал делать по одному за раз, как это:



DELETE FROM [table] WHERE [COL] IN ( '1' )


и до сих пор это в 22 минуты и все еще идет.



таблица содержит 260 000 строк и состоит из четырех столбцов.



есть ли у кого-нибудь идеи, почему это будет так медленно и как ускорить его?
У меня есть не уникальный, некластеризованный индекс на [COL], который я делаю где.
Я использую SQL Server 2008 R2



обновление: у меня нет триггеров на столе.

680   11  

11 ответов:

вещи, которые могут вызвать удаление, чтобы быть медленным:

  • удаление большого количества записей
  • много индексов
  • отсутствуют индексы внешних ключей в дочерних таблицах. (спасибо @CesarAlvaradoDiaz за упоминание об этом в комментариях)
  • тупики и блокировки
  • триггеры
  • каскадное удаление (эти десять родительских записей, которые вы удаляете, могут означать миллионы дочерних записей удаляются)
  • журнал транзакций нужно расти
  • многие внешние ключи для проверки

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

  1. отключить ограничение

    ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;

  2. Отключить Индекс

    ALTER INDEX ALL ON [TableName] DISABLE;

  3. Перестроить Индекс

    ALTER INDEX ALL ON [TableName] REBUILD;

  4. включить ограничение

    ALTER TABLE [TableName] CHECK CONSTRAINT ALL;

  5. удалить

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

delete top (10) YourTable where col in ('1','2','3','4')
while @@rowcount > 0
    begin
    delete top (10) YourTable where col in ('1','2','3','4')
    end

Превентивные Действия

проверьте с помощью SQL Profiler для основной причины этой проблемы. Там может быть Triggers вызывает задержку выполнения. Это может быть что угодно. Не забудьте выбрать Database Name и Object Name при запуске Trace исключить сканирование ненужных запросов...

Фильтрация Имен Баз Данных

Таблица / Хранимая Процедура / Имя Триггера Фильтрация

Корректирующих Действий

как вы сказали, ваша таблица содержит 260 000 записей...и IN Predicate содержит шесть значений. Теперь каждая запись находится в поиске 260 000 раз для каждого значения в IN Predicate. Вместо этого это должно быть внутреннее соединение, как показано ниже...

Delete K From YourTable1 K
Inner Join YourTable2 T on T.id = K.id

вставить IN Predicate значения в Temporary Table или Local Variable

Если таблица, из которой вы удаляете, имеет триггеры Before/AFTER DELETE, что-то там может вызвать вашу задержку.

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

возможно, что другие таблицы имеют ограничение FK для вашей [таблицы]. Поэтому БД необходимо проверить эти таблицы для поддержания ссылочной целостности. Даже если у вас есть все необходимые индексы, соответствующие этим FKs, проверьте их количество.

У меня была ситуация, когда NHibernate неправильно создали дублированный FKs в тех же столбцах, но с разными именами (что разрешено SQL Server). Это резко замедлило выполнение инструкции DELETE.

является ли [COL] действительно символьным полем, которое содержит числа, или вы можете избавиться от одиночных кавычек вокруг значений? @Алекс прав, что в медленнее, чем=, так что если вы можете это сделать, вам будет лучше:

DELETE FROM [table] WHERE [COL] = '1'

но еще лучше использовать числа, а не строки, чтобы найти строки (sql любит числа):

 DELETE FROM [table] WHERE [COL] = 1

может попробовать:

 DELETE FROM [table] WHERE CAST([COL] AS INT) = 1

в любом случае, убедитесь, что у вас есть индекс на столбец [COL], чтобы ускорить сканирование таблицы.

Проверьте план выполнения этого оператора delete. Посмотрите, если используется поиск индекса. Также что такое тип данных col?

Если вы используете неправильный тип данных, измените инструкцию update (например, с '1'на 1 или N'1').

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

Я прочитал эту статью, это было очень полезно для устранения каких-либо неудобств

https://support.microsoft.com/en-us/kb/224453

Это случай waitresource Ключ: 16: 72057595075231744 (ab74b4daaf17)

-- First SQL Provider to find the SPID (Session ID)

-- Second Identify problem, check Status, Open_tran, Lastwaittype, waittype, and waittime
-- iMPORTANT Waitresource select * from sys.sysprocesses where spid = 57

select * from sys.databases where database_id=16

-- with Waitresource check this to obtain object id 
select * from sys.partitions where hobt_id=72057595075231744

select * from sys.objects where object_id=2105058535

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

откройте CMD и запустите эту команду

NET STOP MSSQLSERVER
NET START MSSQLSERVER

это приведет к перезапуску экземпляра SQL Server. попробуйте запустить снова после команды удаления

У меня есть эта команда в пакетном скрипте и запустить его время от времени, если я сталкиваюсь с проблемами, как это. Обычный перезапуск ПК не будет таким же, поэтому перезапуск экземпляра является наиболее эффективным способом, если вы столкнулись с некоторыми проблемами с вашим sql server.

Comments

    Ничего не найдено.