С выходом платформы 1С:Предприятие 8.3.15 архитектура хранения данных регистра бухгалтерии претерпела значительные изменения. Многие специалисты заметили, что при переходе на новые релизы и отключении режима совместимости существенно меняется поведение системы: увеличивается размер базы данных, меняется скорость формирования отчетов и проведения документов. Давайте детально разберем, что именно изменилось в «движке» платформы, почему это напоминает структуру старой доброй 1С 7.7 и как это влияет на повседневную работу системы.
Для начала проанализируем, как данные хранились раньше. В классической архитектуре 1С 8.0–8.3.14 соблюдался принцип нормализации баз данных. Основная таблица движений регистра бухгалтерии (в SQL это таблица _AccRg) содержала только ключевые реквизиты проводки: период, регистратор, счет, суммы и измерения. Сами же значения аналитики (субконто) выносились в отдельную вспомогательную таблицу (_AccRgED). Это позволяло экономить место в базе данных, так как для пустых субконто записи не создавались.
Однако такая структура имела «узкое место» при чтении данных. Чтобы построить Оборотно-сальдовую ведомость с детализацией по контрагентам или номенклатуре, SQL-серверу приходилось выполнять операцию LEFT JOIN между основной таблицей и таблицей значений субконто. При больших объемах данных это создавало серьезную нагрузку на дисковую подсистему и процессор.
Начиная с версии 8.3.15, разработчики платформы реализовали механизм денормализации. Теперь значения субконто дублируются непосредственно в основной таблице движений. Разберем подробнее, что это означает на практике:
ДвиженияДтКт. Все данные, необходимые для отображения проводки с аналитикой, теперь лежат в одной строке одной таблицы._AccRg добавляется значительное количество новых колонок (в типовых конфигурациях около 24 полей). Это поля для хранения типа и значения субконто по дебету и кредиту (SubkontoDt1, SubkontoDt2, SubkontoCt1 и так далее).Опытные разработчики помнят, что в версии 1С:Предприятие 7.7 данные хранились в таблице 1SENTRY (журнал проводок). Там аналитика также записывалась в отдельные колонки Subk1, Subk2 и т.д. в той же самой таблице, где находились суммы. Платформа 8.3.15 фактически вернулась к этой схеме, признав, что для современных СУБД (MS SQL Server, PostgreSQL) «широкие» таблицы с большим количеством индексов работают эффективнее, чем сложные связки нескольких таблиц через JOIN.
Рассмотрим ситуацию с точки зрения производительности. Важно понимать, что это изменение — это компромисс (trade-off) между скоростью чтения и скоростью записи.
Плюсы (ускорение чтения):
Выясним причину, по которой отчеты стали работать быстрее. Раньше для получения остатков по конкретному субконто системе требовалось сначала найти записи в таблице субконто, а затем сопоставить их с основной таблицей. Теперь SQL-сервер может использовать индекс по полям субконто, которые находятся прямо в таблице _AccRg. Это значительно ускоряет:
Остатки, Обороты, ОстаткиИОбороты.Минусы (замедление записи):
Проанализируем обратную сторону медали. При записи набора записей регистра (проведении документа) системе теперь приходится записывать гораздо больше данных в одну таблицу. Кроме того, увеличилось количество индексов, которые SQL-сервер должен обновлять при каждой транзакции. Это может привести к:
Возникает логичный вопрос: если все данные теперь есть в основной таблице, зачем платформа продолжает использовать и заполнять старую таблицу субконто (_AccRgED)? Рассмотрим основные причины:
Во-первых, это необходимо для универсальности запросов. В основной таблице субконто жестко привязаны к позициям (1-е, 2-е или 3-е). Если в запросе к виртуальной таблице вы используете массив видов субконто без привязки к их номеру в плане счетов, платформе проще и быстрее обратиться к «плоской» таблице значений субконто.
Во-вторых, существует вопрос обратной совместимости. Внутренние механизмы платформы и некоторые низкоуровневые функции по-прежнему опираются на старую структуру. Также это актуально для конфигураций, где на одном счете может быть настроено более 3-х субконто (хотя в типовых решениях это встречается редко). Дополнительные субконто сверх лимита полей в основной таблице все равно будут вынесены в отдельную таблицу.
Процесс реструктуризации запускается автоматически при выполнении двух условий:
Важные рекомендации по переходу:
Если ваша информационная база имеет внушительный размер (более 10–20 Гбайт), обычное обновление через «Конфигурация — Обновить конфигурацию базы данных» может затянуться на многие часы или даже привести к ошибке таймаута SQL. В этом случае крайне рекомендуется использовать оптимизированный механизм обновления конфигурации базы данных. Этот механизм позволяет выполнять реструктуризацию фоново, не блокируя работу пользователей на весь период трансформации данных (доступно в версии КОРП).
Посмотрим на пример того, как это выглядит в SQL. Если раньше запрос к движениям выглядел примерно так:
SELECT Acc.Period, Acc.Recorder, Sub.Value
FROM _AccRg Acc
LEFT JOIN _AccRgED Sub ON Acc.EntryID = Sub.EntryID
WHERE Sub.Value = @MyCustomer
То теперь платформа может генерировать запрос напрямую к основной таблице, что гораздо эффективнее для планировщика SQL:
SELECT Period, Recorder, SubkontoDt1
FROM _AccRg
WHERE SubkontoDt1 = @MyCustomer
Мы видим, что 1С идет по пути оптимизации производительности за счет избыточности данных. Несмотря на увеличение размера базы данных, профит от ускорения формирования аналитических отчетов в большинстве случаев перекрывает затраты на хранение. Если после обновления вы заметили замедление, рекомендуется провести замеры производительности. Скорее всего, деградация на записи будет минимальной, а выигрыш на чтении — ощутимым. Однако помните о необходимости наличия свободного места на дисках SQL-сервера перед отключением режима совместимости, так как база неизбежно «подрастет».