У меня есть экземпляр SQL Server 2008 с примерно 150 столбцами. Ранее я заполнил эту таблицу приблизительно 12 миллионами записей, но с тех пор очистил таблицу при подготовке к новому набору данных.
Тем не менее, команды , которые когда - то бегала мгновенно на пустой столик , такой как count(*)
и select top 1000
в SQL Management Studio
настоящее берут эоны бежать.
SELECT COUNT(*) FROM TABLE_NAME
потребовалось 11 минут, чтобы вернуть 0, и SELECT TOP 1000
почти 10 минут, чтобы вернуть пустой стол.
Я также заметил, что свободное место на моем жестком диске буквально исчезло (примерно с 100G до 20G). Единственное, что произошло между ними, был один запрос, который я запустил:
DELETE FROM TABLE_NAME
Что происходит в мире?!?
TRUNCATE TABLE
вместоDELETE FROM
.Ответы:
Вам уже говорили о том, почему
TRUNCATE
было бы намного быстрее / лучше / сексуальнееDELETE
, но все еще остается вопрос:Почему
SELECT
медленнее послеDELETE
завершения ?Это потому,
DELETE
что только призраки строк. Таблица такая же большая, как и тогда, когда в ней было 12 миллионов строк, хотя в ней нет ни одной. Для подсчета строк (0) требуется столько же времени, сколько и для подсчета 12M строк. Со временем процесс очистки призраков соберет эти записи и освободит страницы, которые содержат только призраков, и ваш SELECTs ускорится. Но прямо сейчас, если вы зарегистрируетесьSkipped Ghosted Records/sec
в perfmon, вероятно, стремительный рост во времяSELECT COUNT(*)
. Кроме того, можно ускорить процесс , путем восстановления таблицы:ALTER TABLE ... REBUILD
.TRUNCATE
бы также позаботился об этой проблеме, так как она не оставляет призраков позади.См. Также « Внутри механизма хранения: тщательная очистка призрака» .
источник
DELETE
операторы удаляют строки из таблицы по одной, регистрируя каждую строку вtransaction log
, а также сохраняяlog sequence number (LSN)
информацию. Поскольку вы упомянули, что в вашей таблице хранятся огромные данные (12 миллионов записей), после удаления из которых на жестком диске не осталось места, проверьте размер файла журнала базы данных. Скорее всего, он вырос.Лучшим способом было бы:
источник
(Первоначально это был комментарий к ответу @ DaveE, но я поместил его в собственный ответ, потому что он стал длинным)
TRUNCATE
это вошедший операция. В противном случае он не совместим с ACID. Тем не менее, различия междуTRUNCATE
иDELETE
:TRUNCATE
только журналы страниц / экстентов * освобождаются, тогда какDELETE
регистрируются отдельные строки.TRUNCATE
обычно используется меньше блокировок, так как он использует блокировку таблицы и блокировки страниц, в отличие отDELETE
блокировок строк **.IDENTITY
последовательности:TRUNCATE
сбрасывает идентичную последовательность в таблице, если она присутствует.(* Экстент = 8 страниц.
TRUNCATE
Будет регистрировать / удалять экстенты, если они все из этой таблицы, в противном случае он будет регистрировать / удалять страницы из смешанных экстентов.** Одним из побочных эффектов этого является то, что
DELETE FROM TABLE
потенциально можно оставить пустые страницы, выделенные для таблицы, в зависимости от того, может ли операция получить исключительную блокировку таблицы или нет.Итак (вернемся к исходному вопросу),
TRUNCATE TABLE
безусловно, лучше, чемDELETE FROM TABLE
если вы очищаете таблицу, но хотите сохранить структуру (примечание:TRUNCATE
нельзя использовать для таблицы, на которую ссылается внешний ключ из другой таблицы).Как отмечается в комментарии @ Tullo, также проверьте модель восстановления базы данных - если она заполнена, то вам нужно либо начать делать резервные копии журналов, либо изменить модель восстановления на простую. После того, как вы выполнили одно из этих действий, вы, вероятно, захотите сжать файл журнала как разовую операцию (NB: только файл журнала ), чтобы освободить все это свободное пространство.
Наконец, еще одна вещь, о которой нужно знать - таблица статистики. запустите
UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE`, чтобы оптимизатор запросов не сработал из-за старой статистики.источник
(ПРИМЕЧАНИЕ: я не администратор базы данных). DELETE - это зарегистрированная операция, которая не освобождает используемое пространство. Возможно, у вас большой журнал транзакций, занимающий пространство, и сканирование таблиц выполняется в «пустом» табличном пространстве. Я предполагаю, что вам нужно очистить журнал транзакций и сжать базу данных. Эта статья StackOverflow должна помочь вам начать.
И используйте TRUNCATE TABLE, если вы хотите сделать это в будущем.
РЕДАКТИРОВАТЬ: мое утверждение о том, что TRUNCATE не был зарегистрирован, был ошибочным. удален.
источник