Почему операция Shrink Database не уменьшает размер базы данных 1С на SQL Server и как освободить место

Системный администратор 1С v7.7 IT и автоматизация бизнеса
← На главную

При обслуживании больших информационных баз 1С на платформе MS SQL Server администраторы нередко сталкиваются со следующей ситуацией: после масштабной программной очистки старых периодов или свертки базы (например, удаления документов за прошлые годы) физический размер файла данных .mdf практически не изменяется, даже если была выполнена процедура сжатия (Shrink). При этом файл журнала транзакций .ldf может успешно усекаться, а основной файл базы данных продолжает занимать прежние десятки гигабайт. Разберем детально, почему так происходит и как правильно освободить дисковое пространство.

Почему стандартный Shrink не уменьшает файл данных

Проанализируем внутреннее устройство хранения данных в MS SQL Server и особенности платформы 1С:

  1. Разреженность данных внутри страниц: данные в СУБД хранятся блоками по 8 КБ (страницами). При программном удалении документов через Документ.Удалить(1) команда DELETE удаляет строки из таблиц, освобождая пространство внутри конкретных страниц. Однако сами страницы остаются привязанными к таблицам и индексам. Команда усечения не объединяет полупустые страницы автоматически, из-за чего общий объем выделенного таблицам пространства не уменьшается.
  2. Особенности хранения итогов в 1С 7.7: удаление регистраторов удаляет записи из журнала (_1SJOURN), шапок (DH*), табличных частей (DT*) и движений регистров (RA*). Однако в таблицах итогов регистров (RG*) остаются строки с нулевыми остатками по закрытым периодам и удаленным измерениям. Пока не выполнено специальное сжатие итогов средствами платформы, эти записи физически занимают место.
  3. Механизм усечения по умолчанию: базовый запуск сжатия базы с параметром TRUNCATEONLY лишь отрезает нераспределенное свободное место в самом конце файла базы данных. Если в конце файла расположена хотя бы одна занятая страница данных или объект LOB/BLOB, сжатие хвоста файла останавливается.
  4. Фантомные записи (Ghost Records): при выполнении операторов удаления записи помечаются как удаленные, но физически вычищаются асинхронным фоновым процессом Ghost Cleanup. До завершения этой процедуры пространство не считается освобожденным.

Шаг 1. Пересчет и сжатие итогов в 1С 7.7

Первым делом необходимо навести порядок в таблицах итогов на уровне самой платформы 1С. Простого удаления документов недостаточно — нужно запустить регламентные процедуры платформы:

  1. Запустим 1С:Предприятие 7.7 в монопольном режиме.
  2. Перейдем в главное меню: Операции → Управление итогами.
  3. Выполним полный пересчет итогов и обязательную процедуру Сжатие таблиц итогов.

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

Шаг 2. Оценка реального свободного места в MS SQL Server

Прежде чем выполнять дальнейшие действия с файлами СУБД, проверим, сколько нераспределенного пространства появилось внутри файла данных. Откроем SQL Server Management Studio (SSMS), щелкнем правой кнопкой мыши по нужной базе данных, перейдем в Reports → Standard Reports → Disk Usage. В отчете отобразится соотношение полезных данных и нераспределенного свободного места (Unallocated Space). Если свободного места внутри файла данных существенно больше 20–30%, операция сжатия имеет практический смысл.

Шаг 3. Перестроение индексов (Rebuild)

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


USE [ИмяВашейБазы];
GO

-- Для современных версий SQL Server
EXEC sp_MSforeachtable @command1="PRINT '?' ALTER INDEX ALL ON ? REBUILD";
GO

-- Для старых версий (MS SQL Server 2000 / 2005) можно использовать DBCC DBREINDEX:
-- EXEC sp_MSforeachtable @command1="DBCC DBREINDEX ('?')";
-- GO

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

Шаг 4. Сжатие файла данных с реорганизацией страниц

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

Через графический интерфейс Management Studio:

  1. Щелкнем правой кнопкой мыши по базе данных → Tasks → Shrink → Files.
  2. В поле File type выберем Data.
  3. Установим переключатель Reorganize pages before releasing unused space (Реорганизовать страницы перед освобождением неиспользуемого места).
  4. Зададим целевой размер файла, оставив 10–15% свободного запаса под текущую работу, чтобы избежать мгновенного фрагментирования файла при последующих операциях записи.

Через запрос T-SQL порциями (рекомендуемый способ для больших файлов во избежание зависаний и переполнения журнала транзакций):


USE [ИмяВашейБазы];
GO

-- Узнаем логическое имя файла данных
SELECT name, size/128 AS CurrentSizeMB 
FROM sys.database_files 
WHERE type_desc = 'ROWS';
GO

-- Выполняем постепенное сжатие файла данных шагами (например, по 1000 МБ)
DBCC SHRINKFILE (N'ЛогическоеИмя_Data', 18000);
GO
DBCC SHRINKFILE (N'ЛогическоеИмя_Data', 16000);
GO
DBCC SHRINKFILE (N'ЛогическоеИмя_Data', 14000);
GO

Шаг 5. Очистка и сжатие журнала транзакций (LDF)

Если в процессе массового удаления документов или перестроения индексов сильно разросся файл журнала транзакций (.ldf), сжимать его нужно с учетом модели восстановления базы данных (Recovery Model):

  1. Модель Simple (Простая): усечение лога происходит автоматически после фиксации контрольных точек. Сжатие выполняется напрямую:
    
    USE [ИмяВашейБазы];
    GO
    DBCC SHRINKFILE (N'ЛогическоеИмя_Log', 0);
    GO
    
  2. Модель Full (Полная): пока не выполнена архивация активной части журнала транзакций, MS SQL Server не позволит его усечь, сообщая, что файл используется. Решим эту задачу последовательным созданием резервной копии лога и последующим сжатием:
    
    USE [ИмяВашейБазы];
    GO
    -- Создаем резервную копию журнала транзакций
    BACKUP LOG [ИмяВашейБазы] TO DISK = N'D:\Backup\LogBackup.trn';
    GO
    -- Теперь журнал транзакций готов к усечению
    DBCC SHRINKFILE (N'ЛогическоеИмя_Log', 0);
    GO
    

Важные ограничения и предостережения

При выполнении работ обратим внимание на следующие технические ограничения:

  1. Ограничение выгрузки в .dat в 1С 7.7: штатный механизм выгрузки данных через Конфигуратор (Администрирование → Выгрузить данные) использует встроенный архиватор с жестким лимитом файла архива в 2 ГБ. Попытка выгрузить базу размером 20 ГБ гарантированно приведет к ошибке переполнения архива либо создаст поврежденный файл, который невозможно загрузить. Поэтому способ сжатия через выгрузку/загрузку данных для баз такого размера неприменим.
  2. Фрагментация после сжатия: операция SHRINKFILE перемещает страницы данных из хвоста файла в свободные блоки в начало, что вызывает сильную физическую фрагментацию индексов. После завершения всех процедур сжатия рекомендуется выполнить легкую дефрагментацию (REORGANIZE) или обновить статистику базы данных командой EXEC sp_updatestats;.
  3. Регулярность процедуры: сжатие базы данных не должно быть регулярной регламентной операцией. Ее следует применять исключительно после разовых масштабных удалений больших массивов информации.
← На главную