Как удалить 8 500 000 записей из одной таблицы на сервере SQL - PullRequest
9 голосов
/ 18 января 2010

удалить действия где unt_uid равен нулю

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

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

Это сервер SQL-2005 на 32-разрядной версии Win2003. Второй вопрос: как долго вы оцениваете эту работу (6 часов или 60 часов)? (Да, я знаю, что это зависит от нагрузки, но предположим, что это среда малого бизнеса)

Ответы [ 6 ]

9 голосов
/ 18 января 2010

Вы можете сделать это кусками. Например, каждые 10 секунд выполняйте:

delete from activities where activityid in 
  (select top 1000 activityid from activities where unt_uid is null)

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

5 голосов
/ 18 января 2010

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

3 голосов
/ 18 января 2010

Кто может получить доступ к таблице, будет зависеть от режима изоляции вашей транзакции.

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

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

Вы можете сделать это, разделив таблицу так, чтобы вместо нее можно было просто удалить разделы, или использовать рецепт «скопируйте строки, которые хотите сохранить, а затем удалить таблицу», предложенный другими.

2 голосов
/ 18 января 2010

Я бы использовал технику "nibbling delete". От http://sqladvice.com/blogs/repeatableread/archive/2005/09/20/12795.aspx:

DECLARE @target int
SET @target = 2000
DECLARE @count int
SET @count = 2000

WHILE @count = 2000 BEGIN

 DELETE FROM myBigTable
 WHERE targetID IN
 (SELECT TOP (@target) targetID
  FROM myBigTable WITH(NOLOCK)
  WHERE something = somethingElse) 

 SELECT @count = @@ROWCOUNT
 WAITFOR DELAY '000:00:00.200'

END

Я использовал его именно для этого типа сценария. Значение WAITFOR важно сохранить, оно позволяет другим запросам выполнять свою работу между удалениями.

0 голосов
/ 21 июня 2012

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

0 голосов
/ 18 января 2010

В среде малого бизнеса кажется странным, что вам нужно будет удалить 500 000 строк в стандартном рабочем режиме, не затрагивая других пользователей. Обычно для удаления такого большого размера мы создаем новую таблицу и используем TRUNCATE / INSERT или sp_rename для перезаписи старой.

Сказав, что в особом случае один из моих ежемесячных процессов регулярно может удалять 200-метровые строки партиями по 3 млн. За раз, если обнаружит, что ему необходимо повторно запустить процесс, который сгенерировал эти 200-метровые строки. Но это однопользовательский процесс в выделенной базе данных хранилища данных, и я бы не назвал его сценарием для малого бизнеса.

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

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