Как удалить большую запись с SQL Server?

В базе данных для форума я ошибочно установил тело в nvarchar(MAX). Ну, конечно, кто-то разместил Британскую энциклопедию. Итак, теперь есть тема форума, которая не будет загружаться из-за этого сообщения. Я идентифицировал сообщение и выполнил запрос на удаление, но по какой-то причине запрос просто сидит и вращается. Я отпустил его на пару часов, и он просто сидит там. В конце концов, это будет время.

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

У кого-нибудь еще была эта проблема? Есть ли простой способ разбить эту злую запись на бит?

Обновление: К сожалению, версия SQL Server - 2008.

Вот запрос, который я запускаю, чтобы удалить запись:

DELETE FROM [u413].[replies] WHERE replyID=13461

Я также попытался удалить тему, которая имеет отношение к ответам и удалению по темам, каскадным связанным ответам. Это тоже зависает.

Ответ 1

Вариант 1. Зависит от того, насколько велика сама таблица и насколько велики строки.

  • Скопировать данные в новую таблицу:

    SELECT *
    INTO tempTable
    FROM replies WITH (NOLOCK)
    WHERE replyID != 13461
    

    Хотя это займет время, таблица не должна блокироваться во время процесса копирования

  • Удалить старую таблицу

    DROP TABLE replies
    

    Прежде чем отказаться:
       - script текущие индексы и триггеры, чтобы вы могли позже их воссоздать

       - script и отбросить все внешние ключи в таблицу

  • Переименуйте новую таблицу

    sp_rename 'tempTable', 'replies'
    
  • Восстановить все внешние ключи, индексы и триггеры.

Вариант 2. Разделение.

  • Добавьте новый столбец бит, называемый let say 'Partition', установите для 0 для всех строк, кроме плохого. Установите для него 1 для плохого.

  • Создайте функцию секционирования, чтобы было два раздела 0 и 1.

  • Создайте временную таблицу с той же структурой, что и исходная таблица.

  • Переключите раздел 1 из исходной таблицы в новую временную таблицу.

  • Таблица временных темпов.

  • Удалить раздел из исходной таблицы и удалить новый столбец.

Разделение раздела непросто. В Интернете есть несколько примеров, например. Переключение разделов в SQL Server 2005

Ответ 2

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

SELECT * FROM sys.dm_os_waiting_tasks WHERE session_id = {spid}

Замените {spid} на правильный номер spid соединения, в котором запущена команда DELETE. Чтобы получить это значение, запустите SELECT @@spid перед командой DELETE.

Если столбец sys.dm_os_waiting_tasks.blocking_session_id имеет значение, вы можете использовать монитор активности, чтобы узнать, что делает этот процесс.

Чтобы открыть монитор активности, щелкните правой кнопкой мыши имя сервера в обозревателе объектов SSMS и выберите "Монитор действий". Секции "Процессы и ресурсы" - это те, которые вы хотите.

Ответ 3

Поскольку у вас возникли проблемы с удалением записи и воссозданием таблицы, попробовали ли вы обновить запись?

Что-то вроде (изменение имени поля body в том, что находится в таблице):

update [u413].[replies] set body='' WHERE replyID=13461

Как только вы удалите текст из этой записи одного ответа, вы сможете изменить тип данных столбца, чтобы установить верхнюю границу. Что-то вроде:

alter table [u413].[replies] alter column body nvarchar(100)