Удалить инструкцию в 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
обновление: у меня нет триггеров на столе.
11 ответов:
вещи, которые могут вызвать удаление, чтобы быть медленным:
- удаление большого количества записей
- много индексов
- отсутствуют индексы внешних ключей в дочерних таблицах. (спасибо @CesarAlvaradoDiaz за упоминание об этом в комментариях)
- тупики и блокировки
- триггеры
- каскадное удаление (эти десять родительских записей, которые вы удаляете, могут означать миллионы дочерних записей удаляются)
- журнал транзакций нужно расти
- многие внешние ключи для проверки
таким образом, ваш выбор заключается в том, чтобы выяснить, что блокирует и исправить его или запустить удаление в нерабочее время, когда они не будут мешать нормальной производственной нагрузке. Вы можете запускать удаление в пакетах (полезно, если у вас есть триггеры, каскадное удаление или большое количество записей). Вы можете удалить и пересоздать индексы (лучше, если вы можете сделать это в нерабочее время тоже).
отключить ограничение
ALTER TABLE [TableName] NOCHECK CONSTRAINT ALL;Отключить Индекс
ALTER INDEX ALL ON [TableName] DISABLE;Перестроить Индекс
ALTER INDEX ALL ON [TableName] REBUILD;включить ограничение
ALTER TABLE [TableName] CHECK CONSTRAINT ALL;удалить
удаление большого количества строк может быть очень медленным. Попробуйте удалить несколько за один раз, например:
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