Усеченная таблица 200 ГБ, но дисковое пространство не освобождено

23

У меня осталось только 2 ГБ, поэтому мне нужно удалить эту таблицу истории. Эта таблица сейчас пуста, но дисковое пространство базы данных не освобождено. И файл базы данных составляет 320 ГБ.

Лукас Родригес Сена
источник
Я обнаружил некоторые следы репликации в базе данных, это резко увеличило размер журнала и предотвратило удаление или сжатие.
Лукас Родригес Сена

Ответы:

25

Если вы ссылаетесь на фактическое потребление файла базы данных на томе, то SQL Server не обрабатывает это автоматически . То, что вы удалили данные из базы данных, не означает, что файлы базы данных будут сокращаться, чтобы соответствовать только существующим данным.

То , что вы бы искать, если есть для освобождения места на томе, будет усадка конкретного файла с DBCC SHRINKFILE. Стоит отметить несколько лучших практик, согласно этой документации:

Лучшие практики

Рассмотрите следующую информацию, когда вы планируете сжать файл:

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

  • Большинству баз данных требуется некоторое свободное пространство, чтобы быть доступным для регулярных повседневных операций. Если вы несколько раз сжимаете базу данных и замечаете, что размер базы данных снова увеличивается, это означает, что сокращенное пространство требуется для обычных операций. В этих случаях многократное сжатие базы данных является бесполезной операцией.

  • Операция сжатия не сохраняет состояние фрагментации индексов в базе данных и в целом увеличивает степень фрагментации. Это еще одна причина не многократно сокращать базу данных.

  • Сокращайте несколько файлов в одной базе данных последовательно, а не одновременно. Конфликт в системных таблицах может вызвать задержки из-за блокировки.

Также примечание:

DBCC SHRINKFILE операции могут быть остановлены в любой точке процесса, и любая выполненная работа сохраняется.

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

Первым шагом, безусловно, будет проверка того, сколько места и свободного места вы действительно можете заменить, а также используемого места в файле (ах):

use AdventureWorks2012;
go

;with db_file_cte as
(
    select
        name,
        type_desc,
        physical_name,
        size_mb = 
            convert(decimal(11, 2), size * 8.0 / 1024),
        space_used_mb = 
            convert(decimal(11, 2), fileproperty(name, 'spaceused') * 8.0 / 1024)
    from sys.database_files
)
select
    name,
    type_desc,
    physical_name,
    size_mb,
    space_used_mb,
    space_used_percent = 
        case size_mb
            when 0 then 0
            else convert(decimal(5, 2), space_used_mb / size_mb * 100)
        end
from db_file_cte;
Томас Стрингер
источник
6

Это нормальное поведение при усечении таблицы, которое включает в себя удаление более 128 экстентов, как в « Книгах онлайн»

Когда вы удаляете или перестраиваете большие индексы, или отбрасываете или усекаете большие таблицы, компонент Database Engine откладывает фактические освобождения страниц и связанные с ними блокировки до момента фиксации транзакции. Эта реализация поддерживает как автоматическое принятие, так и явные транзакции в многопользовательской среде, и применяется к большим таблицам и индексам, которые используют более 128 экстентов.

Компонент Database Engine избегает блокировок выделения, необходимых для отбрасывания больших объектов, разделяя процесс на две отдельные фазы: логическую и физическую.

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

Физическая фаза наступает после фиксации транзакции. Единицы распределения, отмеченные для освобождения, физически отбрасываются партиями. Эти отбрасывания обрабатываются внутри коротких транзакций, которые происходят в фоновом режиме, и не требуют много блокировок.

Поскольку физическая фаза наступает после фиксации транзакции, пространство для хранения таблицы или индекса может по-прежнему отображаться как недоступное. Если это пространство требуется для роста базы данных до завершения физической фазы, компонент Database Engine пытается восстановить пространство из единиц выделения, помеченных для освобождения. Чтобы найти пространство, используемое в настоящее время этими единицами выделения, используйте представление каталога sys.allocation_units.

Отложенные операции отбрасывания не освобождают выделенное пространство сразу, и они приводят к дополнительным накладным расходам в компоненте Database Engine. Таким образом, таблицы и индексы, которые используют 128 или менее экстентов, удаляются, усекаются и перестраиваются, как в SQL Server 2000. Это означает, что как логическая, так и физическая фазы происходят до фиксации транзакции.

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

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

SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB
FROM sys.database_files;
Shanky
источник
6

В дополнение к ответам Тома и Шэнки, если ваша база данных содержит данные LOB / BLOB, DBCC SHRINKFILE может не работать. Если это так, то у вас есть два варианта, в зависимости от того, можете ли вы перевести базу данных в автономный режим или нет. Если вы можете перевести базу данных в автономный режим, вам потребуется скопировать данные и скопировать их обратно, чтобы удалить пустое пространство. Вы можете сделать это одним из следующих способов:

  1. Использование оператора SELECT INTO для переноса всей таблицы в новую таблицу. Удалите исходную таблицу, запустите DBCC SHRINKFILE . Переименуйте новую таблицу в исходное имя таблицы.
  2. Используя bcp для копирования таблицы в основном режиме, удалите таблицу, запустите DBCC SHRINKFILE , создайте таблицу и затем скопируйте данные в таблицу.
  3. Использование функции экспорта / импорта для перемещения всех данных в новую базу данных, удаления существующей базы данных, переименования новой базы данных в исходное имя базы данных.

Если вы не можете перевести базу данных в автономный режим, вы можете использовать команду DBCC SHRINKFILE с опцией EMPTYFILE .

Подробности для автономной копии: http://support.microsoft.com/kb/324432/en-us

Текущая информация для опции EMPTYFILE http://msdn.microsoft.com/en-us/library/ms189493(v=sql.105).aspx

stacylaray
источник