Как правильно и безопасно выполнить сжатие (Shrink) базы данных MS SQL после массового удаления данных в 1С?

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

Каждый администратор баз данных СУБД MS SQL Server и специалист 1С рано или поздно сталкивается со следующей ситуацией: в базе данных была проведена масштабная очистка информации. Например, была выполнена свертка информационной базы, удалены устаревшие файлы из томов или очищен массивный регистр сведений, занимавший до 60-90% всего объема базы данных. При этом физический размер файла данных (MDF) на жестком диске остался прежним. Возникает вполне логичное желание вернуть неиспользуемое свободное место операционной системе.

Однако простое нажатие кнопки «Сжать базу данных» (Shrink Database) в среде SQL Server Management Studio (SSMS) может привести к катастрофическому падению производительности всей системы 1С:Предприятие. В этой статье мы подробно разберем физику процессов, происходящих при сжатии файлов данных, выясним разницу между сжатием MDF и LDF, проанализируем специфику работы СУБД под нагрузкой 1С и составим пошаговый безопасный алгоритм действий.

Как устроен процесс сжатия (Shrink) на физическом уровне

Для того чтобы понять опасность операции сжатия, проанализируем внутреннее устройство файлов данных MS SQL Server. Информация в файлах MDF и NDF хранится в виде страниц объемом 8 КБ каждая. Восемь физически последовательных страниц объединяются в структуру, называемую экстентом (Extent) размером 64 КБ.

Когда вы выполняете стандартный шринк базы данных, СУБД запускает алгоритм поиска свободных страниц. Процесс работает по следующему принципу:

  1. SQL Server начинает сканировать файл данных с самого конца в обратном направлении.
  2. Он находит занятую страницу в конце файла.
  3. Затем он ищет первую попавшуюся свободную страницу ближе к началу файла.
  4. СУБД физически копирует данные со страницы из конца файла на свободное место в начале, а исходную страницу помечает как пустую.
  5. Этот процесс повторяется до тех пор, пока вся свободная память не соберется в самом конце файла данных, после чего этот «хвост» отрезается и возвращается операционной системе.

Почему стандартный Shrink уничтожает индексы

Рассмотрим, к каким последствиям приводит такое хаотичное перемещение страниц. Индексы в базах данных (особенно кластерные индексы таблиц 1С) физически упорядочивают строки на диске в соответствии с ключом индекса. Это позволяет СУБД использовать механизм упреждающего чтения (Read-Ahead), когда за один цикл чтения с диска считывается последовательный блок страниц.

Когда механизм сжатия берет страницу из конца файла и вклеивает ее в первое свободное место в начале, логический порядок страниц индекса полностью нарушается. Представьте себе печатную книгу, страницы которой вырвали и произвольно вклеили в пустые места в начале издания, оставив лишь сноски-указатели перехода. Читать такую книгу последовательно станет невозможно — вам придется постоянно перелистывать ее туда-обратно. Аналогично страдает и СУБД: дисковая подсистема перегружается операциями случайного чтения (Random Read), а фрагментация индексов после шринка мгновенно достигает 95–99%. В результате все запросы 1С, считывающие списки, отчеты или проводящие документы, начинают сильно тормозить.

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

Принципиальная разница: сжатие данных (MDF) против сжатия лога (LDF)

Разберем важное различие между двумя типами файлов, так как администраторы часто путают их обслуживание:

Для успешного усечения файла LDF необходимо перевести виртуальные файлы в неактивное состояние. Если ваша база данных находится в модели восстановления Full, сначала обязательно нужно сделать бэкап транзакционного лога, и только после этого выполнять сжатие файла лога. В модели Simple усечение происходит автоматически при достижении контрольной точки (Checkpoint).

Почему профессионалы не используют DBCC SHRINKDATABASE

Команда DBCC SHRINKDATABASE пытается сжать все файлы базы данных разом, включая файлы данных и логов, без какого-либо тонкого контроля над процессом. Вместо этого в профессиональной практике всегда применяется команда сжатия конкретного файла — DBCC SHRINKFILE.

Рассмотрим её ключевые преимущества:

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

Выясним подробнее, как работает параметр TRUNCATEONLY. Если выполнить следующую команду:


-- Безопасное отсечение пустого хвоста файла данных
DBCC SHRINKFILE (LogicalFileName, TRUNCATEONLY);

В этом случае SQL Server вообще не перемещает страницы данных внутри файла. Он не вызывает фрагментацию индексов. СУБД просто находит свободное пространство, которое образовалось на самом «хвосте» файла (например, после удаления последней по порядку таблицы), отрезает его и возвращает операционной системе. Это абсолютно безопасная и быстрая операция.

Специфика 1С: Ловушка авторасширения и мгновенная инициализация файлов (IFI)

В высоконагруженных системах 1С сжатие файлов данных таит в себе еще одну неочевидную опасность. Предположим, вы успешно выполнили шринк и сжали файл данных MDF с 500 ГБ до 100 ГБ. Однако на следующий день пользователи запускают операцию закрытия месяца, расчет себестоимости или реструктуризацию метаданных. 1С начинает массово записывать новые данные, и СУБД запрашивает у операционной системы увеличение файла (Autogrow).

По умолчанию при каждом расширении файла данных операционная система Windows заполняет выделенный объем физического диска нулями (Zeroing). В этот момент выполнение любых транзакций пользователей 1С полностью приостанавливается. Пользователи видят зависание программы или получают ошибки таймаута соединения.

Для решения этой проблемы на сервере СУБД должна быть активирована функция Мгновенной инициализации файлов (Instant File Initialization — IFI). Выясним, как ее включить:

  1. Откройте локальную политику безопасности Windows (secpol.msc) на сервере с MS SQL Server.
  2. Перейдите в раздел «Локальные политики» -> «Назначение прав пользователя».
  3. Найдите политику «Выполнение задач по обслуживанию томов» (Perform volume maintenance tasks).
  4. Добавьте учетную запись, под которой запущена служба SQL Server, в список пользователей этой политики.
  5. Перезапустите службу SQL Server.

После этого файлы данных (MDF) будут прирастать мгновенно, не блокируя работу пользователей 1С. Тем не менее, помните, что для файлов логов (LDF) технология мгновенной инициализации физически неприменима — они всегда заполняются нулями при расширении.

Особенности TempDB в среде 1С

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

Попытки выполнить шринк базы TempDB на «живом» работающем сервере обычно заканчиваются неудачей, так как активные сессии пользователей непрерывно используют временные объекты и блокируют файлы. Сжимать TempDB вручную не рекомендуется. Самый надежный, чистый и производительный способ вернуть размер TempDB к первоначальным настройкам — это запланированный перезапуск службы SQL Server в технологическое окно. При каждом старте СУБД база TempDB пересоздается заново.

Правильный алгоритм действий при массовом удалении данных

Вернемся к практической задаче автора темы: в базе была очищена крупная таблица (или удалено 90% записей), и требуется вернуть место операционной системе без ущерба для производительности 1С. Разберем по шагам, как выполнить это правильно.

Шаг 1. Очистка данных

Если требуется очистить таблицу полностью, по возможности всегда используйте команду TRUNCATE TABLE вместо DELETE. Это работает мгновенно и практически не нагружает журнал транзакций, так как СУБД просто освобождает страницы, а не логирует удаление каждой строки отдельно. Если удаление выполняется выборочно (с условием WHERE), делайте это небольшими порциями (батчами), чтобы не заблокировать всю таблицу и не переполнить лог транзакций.

Шаг 2. Оценка объема свободного места

Перед выполнением любых сжатий оцените реальный объем свободного места внутри файлов базы данных с помощью стандартного отчета в SSMS: нажмите правой кнопкой на базу -> «Отчеты» (Reports) -> «Стандартные отчеты» (Standard Reports) -> «Дисковое пространство» (Disk Usage).

Шаг 3. Безопасное сжатие файла данных малыми порциями

Никогда не сжимайте файл данных одной командой до упора. Сжатие гигантского файла за один раз создаст колоссальную нагрузку на диски и лог транзакций, из-за чего процесс может зависнуть на много часов. Выполняйте сжатие итеративно, уменьшая размер файла порциями по 5–10 ГБ. Используйте команду DBCC SHRINKFILE:


-- Пример постепенного сжатия файла данных до целевого объема в 120 ГБ
-- Предположим, текущий размер файла 150 ГБ. Сжимаем сначала до 140 ГБ:
DBCC SHRINKFILE (N'Имя_Файла_Данных', 140000);
GO
-- Затем до 130 ГБ:
DBCC SHRINKFILE (N'Имя_Файла_Данных', 130000);
GO
-- И до целевых 120 ГБ:
DBCC SHRINKFILE (N'Имя_Файла_Данных', 120000);
GO

Важное примечание: никогда не сжимайте файл «впритык» к объему реальных данных. Всегда оставляйте запас свободной памяти в файле данных не менее 10-15%. Это предотвратит немедленный запуск авторасширения при первой же транзакции.

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

После завершения сжатия ваши индексы будут тотально фрагментированы. Необходимо в обязательном порядке восстановить их структуру. Выполните полное перестроение индексов. Для этого можно использовать планы обслуживания (Maintenance Plans) или запустить скрипт:


-- Перестроение всех индексов во всей базе данных
-- Внимание: операция требует свободного места в базе данных
-- и блокирует таблицы (в редакции SQL Server Standard)
ALTER INDEX ALL ON Имя_Таблицы REBUILD WITH (ONLINE = ON);

Обратите внимание: операция REBUILD затребует дополнительное временное пространство внутри файла данных для построения новых страниц индексов, поэтому размер файла MDF после перестроения незначительно вырастет. Это абсолютно нормально и необходимо для обеспечения высокой скорости работы 1С.

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

В процессе удаления данных и последующего перестроения индексов ваш файл журнала транзакций LDF неизбежно увеличится. Выполните бэкап журнала транзакций (в модели Full), после чего сожмите файл лога до разумных технологических размеров (например, до 10-20 ГБ в зависимости от нагрузки):


-- Сжатие файла журнала транзакций до 10 ГБ
DBCC SHRINKFILE (N'Имя_Файла_Лога', 10000);

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

← На главную