Поделиться через


DBCC SHRINKFILE (Transact-SQL)

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

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

Примечание.

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

Соглашения о синтаксисе Transact-SQL

Синтаксис

DBCC SHRINKFILE   
(  
    { file_name | file_id }   
    { [ , EMPTYFILE ]   
    | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATEONLY } ] ]  
    }  
)  
[ WITH 
  {     
      [ WAIT_AT_LOW_PRIORITY 
        [ ( 
            <wait_at_low_priority_option_list>
        )] 
      ] 
      [ , NO_INFOMSGS]
  }
]
       
< wait_at_low_priority_option_list > ::=  
    <wait_at_low_priority_option>
    | <wait_at_low_priority_option_list> , <wait_at_low_priority_option>
 
< wait_at_low_priority_option > ::=
    ABORT_AFTER_WAIT = { SELF | BLOCKERS }

Аргументы

file_name

Логическое имя файла, предназначенного для сжатия.

file_id

Идентификационный номер (идентификатор) файла, предназначенного для сжатия. Чтобы получить идентификатор файла, используйте системную функцию FILE_IDEX или выполните запрос к представлению каталога sys.database_files в текущей базе данных.

target_size

Целое число, представляющее новый размер мегабайта файла. Если файл не указан или не указан или 0, DBCC SHRINKFILE уменьшается до размера создания файла.

Вы можете уменьшить размер пустого файла по умолчанию с помощью DBCC SHRINKFILE <target_size>. Например, при создании файла с размером 5 МБ и последующем уменьшении размера до 3 МБ, в то время как файл остается пустым, размер файла по умолчанию задается равным 3 МБ. Это правило применимо только к пустым файлам, в которых никогда не содержались данные.

Контейнеры файловых групп FILESTREAM не поддерживают этот параметр.

При указании DBCC SHRINKFILE пытается уменьшить размер файла до target_size. Используемые страницы в освобождаемой области файла перемещаются в свободное пространство в сохраняемых областях файла. Например, с файлом данных размером 10 МБ операция DBCC SHRINKFILE с 8 target_size перемещает все использованные страницы в последние 2 МБ файла на любые нераспределенные страницы в первом 8 МБ файла. DBCC SHRINKFILE не сжимает файл после необходимого размера сохраненных данных. Например, если используется 7 МБ файла данных размером 10 МБ, DBCC SHRINKFILE инструкция с target_size 6 уменьшает размер файла до 7 МБ, а не 6 МБ.

EMPTYFILE

Переносит все данные из указанного файла в другие файлы в той же файловой группе. Другими словами, EMPTYFILE перенос данных из указанного файла в другие файлы в той же файловой группе. EMPTYFILE гарантирует, что новые данные не добавляются в файл, несмотря на то, что этот файл не только для чтения. Для удаления файла можно использовать инструкцию ALTER DATABASE. При использовании инструкции ALTER DATABASE для изменения размера файла флаг только для чтения сбрасывается, а данные можно добавить.

Для контейнеров файловой группы FILESTREAM нельзя использовать ALTER DATABASE для удаления файла, пока сборщик мусора FILESTREAM не будет запущен и удален все ненужные файлы контейнеров файловой группы, EMPTYFILE скопированные в другой контейнер. Дополнительные сведения см. в разделе sp_filestream_force_garbage_collection. Сведения об удалении контейнера FILESTREAM см. в соответствующем разделе в статье Параметры инструкции ALTER DATABASE для файлов и файловых групп (Transact-SQL)

EMPTYFILE не поддерживается в База данных SQL Azure или гипермасштабировании База данных SQL Azure.

NOTRUNCATE

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

NOTRUNCATE применимо только к файлам данных. Файлы журнала не затрагиваются.

Контейнеры файловых групп FILESTREAM не поддерживают этот параметр.

TRUNCATEONLY

Освобождает все свободное место в конце файла в операционной системе, но не выполняет никаких перемещений страниц внутри файла. Файл данных сокращается только до последнего выделенного экстента.

target_size игнорируется при указании TRUNCATEONLY.

Параметр TRUNCATEONLY не перемещает сведения в журнале, но удаляет неактивные VLFs из конца файла журнала. Контейнеры файловых групп FILESTREAM не поддерживают этот параметр.

WITH NO_INFOMSGS

Подавляет вывод всех информационных сообщений.

WAIT_AT_LOW_PRIORITY с операциями сжатия

Область применения: SQL Server 2022 (16.x) и более поздних версий, База данных SQL Azure, Управляемый экземпляр SQL Azure

Функция ожидания с низким приоритетом снижает состязание за блокировку. Дополнительные сведения см. в разделе Основные сведения о проблемах параллелизма в DBCC SHRINKDATABASE.

Эта функция похожа на WAIT_AT_LOW_PRIORITY с операциями индексирования в режиме "в сети", с некоторыми различиями.

  • Нельзя задать значение NONE для параметра ABORT_AFTER_WAIT.

WAIT_AT_LOW_PRIORITY

Область применения: SQL Server (SQL Server 2022 (16.x) и более поздних версий) и База данных SQL Azure.

При выполнении команды сжатия в режиме WAIT_AT_LOW_PRIORITY новые запросы, требующие блокировки стабильности схемы (Sch-S), не блокируются ожидающей операцией сжатия, пока она не прекратит ожидание и не начнет выполняться. Операция сжатия будет выполняться, когда сможет получить блокировку изменения схемы (Sch-M). Если новая операция сжатия в режиме WAIT_AT_LOW_PRIORITY не может получить блокировку из-за длительного запроса, операция сжатия в конечном итоге будет истекать через 1 минуту по умолчанию и будет автоматически выйти.

Если новая операция сжатия в режиме WAIT_AT_LOW_PRIORITY не может получить блокировку из-за длительного запроса, операция сжатия в конечном итоге будет истекать через 1 минуту по умолчанию и будет автоматически выйти. Это произойдет, если операция сжатия не может получить блокировку Sch-M из-за параллельных запросов или запросов, содержащих блокировки Sch-S. По истечении времени ожидания в журнал ошибок SQL Server будет отправлено сообщение об ошибке 49516, например: Msg 49516, Level 16, State 1, Line 134 Shrink timeout waiting to acquire schema modify lock in WLP mode to process IAM pageID 1:2865 on database ID 5. На этом этапе можно просто повторить операцию сжатия в режиме WAIT_AT_LOW_PRIORITY, зная, что это не окажет никакого влияния на приложение.

ABORT_AFTER_WAIT = [ SELF | BLOCKERS ]

Область применения: SQL Server (SQL Server 2022 (16.x) и более поздних версий) и База данных SQL Azure.

  • SELF

    Прекратить текущую операцию сжатия файла без выполнения какого-либо действия.

  • BLOCKERS

    Остановить все пользовательские транзакции, в данный момент блокирующие операцию сжатия файла, чтобы можно было продолжить данную операцию. Параметр BLOCKERS требует, чтобы у имени входа было разрешение ALTER ANY CONNECTION.

Результирующий набор

В приведенной ниже таблице описаны столбцы результирующего набора.

Имя столбца Description
DbId Идентификационный номер базы данных файла, ядро СУБД пытался уменьшиться.
FileId Идентификационный номер файла, ядро СУБД попытался сжаться.
CurrentSize Количество 8-килобайтных страниц, занятых файлом в настоящее время.
MinimumSize Минимальное количество 8-килобайтных страниц, которое может занимать файл. Это число соответствует минимальному размеру файла при его создании.
UsedPages Количество 8-килобайтных страниц, используемых файлом в настоящее время.
EstimatedPages Количество страниц размером 8 КБ, на которые ядро СУБД оценивается, что файл может сократиться.

Замечания

DBCC SHRINKFILE применяется к файлам текущей базы данных. Дополнительные сведения об изменении текущей базы данных см. в статье USE (Transact-SQL).

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

При сбое DBCC SHRINKFILE операции возникает ошибка.

Другие пользователи могут работать в базе данных во время сжатия файлов; База данных не должна находиться в однопользовательском режиме. Для сжатия системных баз данных не требуется запускать экземпляр SQL Server в однопользовательском режиме.

При указании WAIT_AT_LOW_PRIORITY запрос блокировки sch-M операции сжатия будет ждать с низким приоритетом при выполнении команды в течение 1 минуты. Если операция заблокирована в течение длительности, будет выполнено указанное ABORT_AFTER_WAIT действие.

Операции сжатия баз данных и файлов в настоящее время находятся в предварительной версии для База данных SQL Azure гипермасштабирования. Дополнительные сведения о предварительной версии см. в разделе "Сжатие" для База данных SQL Azure гипермасштабирования.

Известные проблемы

Область применения: SQL Server, База данных SQL Azure, Управляемый экземпляр SQL Azure, выделенный пул SQL Azure Synapse Analytics

  • В настоящее время типы столбцов LOB (varbinary(max), varchar(max)и nvarchar(max)) в сжатых сегментах columnstore не затрагиваются DBCC SHRINKDATABASE и DBCC SHRINKFILE.

Общие сведения о проблемах параллелизма с DBCC SHRINKFILE

Команды сжатия базы данных и сжатия файлов могут привести к проблемам параллелизма, особенно при активном обслуживании, таком как перестроение индексов, или в загруженных средах OLTP. Когда приложение выполняет запросы к таблицам базы данных, эти запросы будут получать и поддерживать блокировку стабильности схемы (Sch-S), пока не завершат свои операции. При попытке освободить место во время регулярного использования операции сжатия базы данных и сжатия файлов в настоящее время требуют блокировки изменения схемы (Sch-M) при перемещении или удалении страниц карты распределения индекса (IAM), блокируя блокировки Sch-S, необходимые для пользовательских запросов. В результате длительные запросы блокируют операцию сжатия до завершения выполнения запросов. Это означает, что все новые запросы, требующие блокировок Sch-S, также помещаются в очередь за операцией сжатия в ожидании, и кроме этого, они будут заблокированы, что еще больше усугубит эту проблему параллелизма. Это может значительно повлиять на производительность запросов приложений, а также вызвать трудности при выполнении необходимого обслуживания для сжатия файлов базы данных. В sql Server 2022 (16.x) ожидание сжатия при низком приоритете устраняет эту проблему, принимая блокировку изменения схемы в WAIT_AT_LOW_PRIORITY режиме. Дополнительные сведения см. на странице WAIT_AT_LOW_PRIORITY с операциями сжатия.

Дополнительные сведения о блокировках Sch-S и Sch-M см. в руководстве по блокировке и управлению версиями строк транзакций.

Сжатие файла журнала

Для файлов журналов ядро СУБД использует target_size для вычисления целевого размера всего журнала. Таким образом, target_size указывает размер свободного места в журнале после операции сжатия. Затем по заданному размеру всего журнала рассчитываются заданные размеры каждого файла журнала. DBCC SHRINKFILE пытается немедленно уменьшить размер каждого физического журнала до целевого размера. Однако если часть логического журнала находится в виртуальных журналах за пределами целевого размера, ядро СУБД освобождает максимальное пространство, а затем выдает информационное сообщение. Сообщение описывает действия, которые необходимо предпринять, чтобы переместить логический журнал из виртуальных журналов в конец файла. После выполнения DBCC SHRINKFILE действий можно использовать для освобождения оставшегося пространства.

Так как файл журнала можно сжать только до границы виртуального файла журнала, сжать файл журнала до меньшего размера, чем у виртуального файла журнала, нельзя, даже если он не используется. Ядро СУБД динамически выбирает размер журнала виртуального файла при создании или расширении файлов журнала.

Рекомендации

Примите во внимание следующие сведения при планировании сжатия файла.

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

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

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

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

Устранение неполадок

В этом разделе описывается, как диагностировать и исправлять проблемы, которые могут возникнуть при выполнении DBCC SHRINKFILE команды.

Файл не сжимается

Если размер файла не изменяется после сжатия, которое было выполнено без ошибок, проверьте, есть свободное место в файле, с помощью следующей команды:

  • Выполните следующий запрос.
SELECT name
    , size / 128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT) / 128.0 AS AvailableSpaceInMB
FROM sys.database_files;
  • Выполните команду DBCC SQLPERF, чтобы освободить пространство, используемое журналом транзакций.

Если свободного пространства недостаточно, сжатие не поможет уменьшить размер файла.

Чаще всего результаты сжатия незаметны для файлов журнала. Такая несжимаемость характерна для неусеченных файлов журнала. Чтобы усечь журнал, можно задать для модели восстановления базы данных значение SIMPLE или создать резервную копию журнала, а затем снова запустить DBCC SHRINKFILE операцию.

Операция сжатия блокируется

Транзакция, запущенная под уровнем изоляции с управлением версиями строк, может блокировать операции сжатия. Например, если выполняется большая операция удаления, выполняемая под уровнем изоляции на основе версий строк, выполняется при DBCC SHRINKDATABASE выполнении операции сжатия, операция сжатия ожидает завершения удаления перед продолжением. Когда эта блокировка происходит, DBCC SHRINKFILE и DBCC SHRINKDATABASE операции печатают информационное сообщение (5202 для SHRINKDATABASE и 5203 для SHRINKFILE) в журнал ошибок SQL Server. Это сообщение регистрируется каждые 5 минут в течение первого часа, а затем по одному разу каждый час Например, если журнал ошибок содержит следующее сообщение об ошибке, произойдет следующая ошибка.

DBCC SHRINKFILE for file ID 1 is waiting for the snapshot
transaction with timestamp 15 and other snapshot transactions linked to
timestamp 15 or with timestamps older than 109 to finish.

Такое сообщение означает, что операция сжатия блокируется транзакциями с моментальным снимком, отметка времени которого старше, чем 109 (это последняя транзакция, завершенная операцией сжатия). Он также указывает transaction_sequence_numfirst_snapshot_sequence_num столбцы или столбцы в динамическом представлении управления sys.dm_tran_active_snapshot_database_transactions содержит значение 15. transaction_sequence_num Если столбец или first_snapshot_sequence_num столбец представления содержит число меньше последней завершенной транзакции операции сжатия (109), операция сжатия ожидает завершения этих транзакций.

Разрешить эту проблему можно одним из следующих способов.

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

Разрешения

Необходимо быть членом предопределенной роли сервера sysadmin или предопределенной роли базы данных db_owner .

Примеры

А. Сжатие файла данных до указанного целевого размера

В приведенном ниже примере файл данных с именем DataFile1 в пользовательской базе данных UserDB сжимается до 7 МБ.

USE UserDB;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

B. Сжатие файла журнала до указанного целевого размера

В следующем примере файл журнала в базе данных AdventureWorks2022 сжимается до 1 МБ. Чтобы разрешить DBCC SHRINKFILE команде уменьшить файл, файл сначала усечен, установив для модели восстановления базы данных значение SIMPLE.

USE AdventureWorks2022;
GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE AdventureWorks2022
SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE (AdventureWorks2022_Log, 1);
GO
-- Reset the database recovery model.
ALTER DATABASE AdventureWorks2022
SET RECOVERY FULL;
GO

В. Усечение файла данных

В следующем примере усекается первичный файл данных в базе данных AdventureWorks2022. Выполняется запрос к представлению каталога sys.database_files для получения идентификатора файла данных file_id.

USE AdventureWorks2022;
GO
SELECT file_id, name
FROM sys.database_files;
GO
DBCC SHRINKFILE (1, TRUNCATEONLY);

D. Пустой файл

Следующий пример демонстрирует процедуру очистки файла для его удаления из базы данных. Для этого примера сначала создается файл, содержащий данные.

USE AdventureWorks2022;
GO
-- Create a data file and assume it contains data.
ALTER DATABASE AdventureWorks2022
ADD FILE (
    NAME = Test1data,
    FILENAME = 'C:\t1data.ndf',
    SIZE = 5MB
    );
GO
-- Empty the data file.
DBCC SHRINKFILE (Test1data, EMPTYFILE);
GO
-- Remove the data file from the database.
ALTER DATABASE AdventureWorks2022
REMOVE FILE Test1data;
GO

Е. Сжатие файла базы данных с помощью WAIT_AT_LOW_PRIORITY

В приведенном ниже примере выполняется попытка сжатия файла данных в текущей пользовательской базе данных до 1 МБ. Выполняется запрос к представлению каталога sys.database_files для получения file_id файла данных, в этом примере file_id 5. Если блокировка не может быть получена в течение одной минуты, операция сжатия прерывается.

USE AdventureWorks2022;
GO

SELECT file_id, name
FROM sys.database_files;
GO

DBCC SHRINKFILE (5, 1) WITH WAIT_AT_LOW_PRIORITY (ABORT_AFTER_WAIT = SELF);