Как удалить большую запись с 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)