Простой оператор SQL Delete, указывающий время ожидания - PullRequest
8 голосов
/ 28 июля 2011

При выполнении этого простого оператора SQL Delete я получаю тайм-аут от SQL Server:

DELETE FROM dbo.[User] WHERE Id = 95146

В таблице около 95.000 записей.

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

Я также удалил всю созданную мной статистику, но безрезультатно.

Что еще я могу сделать, чтобы оптимизировать для этого?

С уважением, David

Ответы [ 5 ]

15 голосов
/ 28 июля 2011

Сколько внешних ключей у вас есть, ссылаясь на столбец Id в Users, и есть ли индексы для этих столбцов?

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

4 голосов
/ 17 августа 2015

Я боролся с оператором DELETE, который заставлял нашу систему ERP (Epicor 10) отключаться по ночам при выполнении MRP. Это было удаление с несколькими объединениями, и одна из таблиц, включенных в объединение, довольно большая. Странно было то, что если бы я преобразовал удаление в SELECT * для того же предложения joins / where, то запрос завершился бы мгновенно и имел бы нулевые результаты (т. Е. Оператор delete явно выполнял некоторое длинное сканирование большой таблицы, но это на самом деле не нашел ничего для удаления).

Что в итоге помогло, я запустил выбранную версию устава с включенным Показать фактический план выполнения , и в нем был предложен Неуникальный индекс для добавления в одну из таблиц. После того, как я добавил этот индекс, оператор SELECT по-прежнему выполнялся мгновенно, но теперь также и оператор delete!

3 голосов
/ 28 июля 2011

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

SELECT f.name AS ForeignKey,
    OBJECT_NAME(f.parent_object_id) AS TableName,
    COL_NAME(fc.parent_object_id,fc.parent_column_id) AS ColumnName,
    OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
    COL_NAME(fc.referenced_object_id,
    fc.referenced_column_id) AS ReferenceColumnName,
    f.delete_referential_action_desc
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
2 голосов
/ 28 июля 2011

Пока ваш оператор выполняется, взгляните на список запущенных задач и блокировок, снятых системой.Вы можете получить эту информацию из Activity Monitor или посмотреть запущенные задачи в представлении sys.dm_os_waiting_tasks и заблокировать с помощью exec sp_lock и sys.dm_tran_locks.

Кроме того, в SQL Server Management Studio введите этот оператор и посмотрите примерный план выполнения.Возможно, вы сможете увидеть, что пытается сделать SQL Server.

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

0 голосов
/ 28 июля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...