Каталог решений - Сжатие баз данных 1С:Предприятие в MS SQL Server

Сжатие баз данных 1С:Предприятие в MS SQL Server

Сжатие баз данных 1С:Предприятие в MS SQL Server

В наличии

Тема сжатия баз данных 1С в настоящий момент довольно часто обсуждается. Достоинства сжатия известны – уменьшение размера базы данных, уменьшение нагрузки на дисковую подсистему и некоторое ускорение выполнения тяжелых операций чтения/записи. Из недостатков – небольшое увеличение нагрузки на процессоры сервера СУБД за счет расхода ресурсов на компрессию/декомпрессию данных. Но при использовании в качестве MSSQL и DB2 (за Oracle и PostgreSQL не скажу, т.к. не знаю) есть один «подводный камень» — при выполнении реструктуризации происходит декомпрессия новых таблиц и индексов. Происходить это может как при выполнении обновления конфигурации с изменением структуры метаданных, так и при выполнении тестирования и исправления ИБ (реиндексация пересоздает только индексы, а реструктуризация – и таблицы, и индексы). «Проблема» кроется в том, что признак сжатия устанавливается индивидуально для каждой таблицы и индекса.

Категория:

Описание

Решение проблемы для MS SQL Server.

В течение долгого времени сжатие было доступно только в Enterprise версиях MS SQL Server, но начиная с SQL2016 Service Pack 1 эта функциональность была включена во всех редакциях, в том числе, бесплатной Express (релиз от 16.11.2016 — https://blogs.msdn.microsoft.com/sqlreleaseservices/sql-server-2016-service-pack-1-sp1-released/).
Поймать момент создания новой таблицы или индекса возможно с помощью DDL-триггера, который вызывается сразу после выполнения CREATE TABLE/INDEX, но до начала переноса данных платформой 1С. Триггер данного типа можно создать как для конкретной ИБ, так и для всего сервера. Создание триггера для ИБ не вписывается в лицензионное соглашение 1С, поэтому лучше создавать для всего сервера, тем более что это позволит обслуживать сразу все базы на данном сервере.

Создание DDL-триггера для операции создания таблицы:

CREATE TRIGGER [data_compression]
ON ALL SERVER
AFTER CREATE_TABLE
AS
—Текст триггера

Создание DDL-триггера для операции создания индекса:

CREATE TRIGGER [index_compression]
ON ALL SERVER
AFTER CREATE_INDEX
AS
—Текст триггера

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

ALTER TABLE [имя базы].[имя схемы].[имя таблицы] REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE)

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

ALTER INDEX [имя индекса] ON [имя базы].[имя схемы].[имя таблицы] REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE)

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

Ниже приведу решение в том виде, как оно используется у нас. Это позволило автоматически применить сжатие для всех баз данных на сервере.

Создана служебная база CompressionSetting с двумя таблицами:

1)    Databases — для хранения списка баз, которые сжимать НЕ требуется.

CREATE TABLE [dbo].[Databases](
    [name] [nvarchar](100) NULL,
    [active] [int] NULL
) ON [PRIMARY]

Из ~200 баз на сервере я внес в эту таблицу только одну – tempdb:

2)    Trace – для мониторинга работы DDL-триггеров

CREATE TABLE [dbo].[trace](
    [text] [nvarchar](max) NULL,
    [DatabaseName] [nvarchar](max) NULL,
    [DateTime] [datetime] NULL
) ON [PRIMARY]


 
Далее создал 2 DDL-триггера:

1)    Для таблиц

CREATE TRIGGER [data_compression] 

ON ALL SERVER 
AFTER CREATE_TABLE 
AS 
DECLARE @SchemaName nvarchar(150),

@ObjectName nvarchar(150),
@DatabaseName nvarchar(150),
@cmd nvarchar(500)

--Получим имя схемы из выполняемой команды CREATE TABLE 
SET @SchemaName = EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]','nvarchar(150)')
--Получим имя таблицы
SET @ObjectName = EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(150)')

--Получим имя базы
SET @DatabaseName = EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(150)')
--Сформируем из полученных данных требуемую команду на установку признака сжатия для таблицы
set @cmd = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @ObjectName + '] REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE)'

--Теперь проверяем настройки – если базы нет в таблице CompressionSetting.dbo.Databases с признаком Active = 1, то выполняем команду, иначе игнорируем
IF NOT EXISTS (SELECT  1 AS Expr1
			FROM CompressionSetting.dbo.Databases AS T
			WHERE (name = @DatabaseName) AND Active = 1) 

BEGIN 
	INSERT INTO CompressionSetting.dbo.trace (text, DatabaseName, DateTime) SELECT @cmd, @DatabaseName, GETDATE()

	EXEC (@cmd) 
END
ELSE 
BEGIN 
	PRINT 'TEST'

END

2)    Для индексов

CREATE TRIGGER [index_compression]
ON ALL SERVER
AFTER CREATE_INDEX

AS
DECLARE @SchemaName nvarchar(150),
@ObjectName nvarchar(150),
@TargetObjectName nvarchar(150),

@DatabaseName nvarchar(150),
@cmd nvarchar(500)
--Получим имя схемы из выполняемой команды CREATE INDEX
SET @SchemaName = EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]','nvarchar(150)')

--Получим имя индекса
SET @ObjectName = EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(150)')
--Получим имя таблицы
SET @TargetObjectName = EVENTDATA().value('(/EVENT_INSTANCE/TargetObjectName)[1]','nvarchar(150)')

--Получим имя базы
SET @DatabaseName = EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(150)')
--Сформируем из полученных данных требуемую команду на установку признака сжатия для индекса
set @cmd = 'ALTER INDEX [' + @ObjectName + '] ON [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TargetObjectName + '] REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE)'

--Теперь проверяем настройки – если базы нет в таблице CompressionSetting.dbo.Databases с признаком Active = 1, то выполняем команду, иначе игнорируем
IF NOT EXISTS (SELECT  1 AS Expr1
            FROM CompressionSetting.dbo.Databases AS T
            WHERE (name = @DatabaseName) AND Active = 1)

BEGIN
    INSERT INTO CompressionSetting.dbo.trace (text, DatabaseName, DateTime) SELECT @cmd, @DatabaseName, GETDATE()

    EXEC (@cmd)
END
ELSE
BEGIN
    PRINT 'TEST'

END

Сразу после создания триггеров никаких изменений в размере баз, конечно, не произойдет. Для сжатия уже имеющихся баз можно воспользоваться следующими методами:
1)    Написать скрипт для поочередного перебора таблиц и индексов и установки для них признака сжатия. Мне этот вариант не понравился, т.к. на сжатие больших таблиц требуется очень много времени, база при этом раздувается, а потом очень долго уменьшается через SHRINK DATABASE.
2)    Выполнить полную реструктуризацию через «Тестирование и исправление» . По времени быстрее, но база также раздувается и ее потом придется уменьшать через SHRINK DATABASE.
3)    Самый оптимальный вариант, на мой взгляд – пересоздать базу через dt-файл. При этом готовая база изначально будет минимального размера, а время загрузки базы со сжатием мало отличается от загрузки в обычном режиме.

Относительно допустимости применения подобного метода сжатия я задавал вопрос в партнерской конференции, на что был в итоге получен следующий комментарий Сергея Нуралиева:

«…Можно считать позицией то, что мы считаем, что использование  этих возможностей должно быть или запрещено или разрешено, но с адекватной поддержкой (методологической или программной). Вариант использования их без надлежащей поддержки мы считаем неправильным, так как он приводит к проблемам в администрировании.»

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

has been added to your cart:
Оформление заказа