При разработке сложных учетных систем на платформе 1С:Предприятие 8 мы часто сталкиваемся с ситуацией, когда документ содержит десятки реквизитов, по которым в дальнейшем требуется получать остатки и обороты. Это могут быть номенклатура, склады, организации, подразделения, статьи движения, менеджеры, проекты и даже специфические свойства заказов. Встает закономерный вопрос: как спроектировать регистры накопления так, чтобы система работала быстро, не блокировалась при параллельной работе и выдавала отчеты за приемлемое время? Рассмотрим основные архитектурные подходы и проанализируем их сильные и слабые стороны.
Первый и самый очевидный вариант — создать один регистр накопления, где каждое аналитическое поле документа станет измерением регистра. Проанализируем этот путь подробнее. Платформа 1С позволяет добавлять большое количество измерений, и с точки зрения простоты написания кода это идеальный вариант. Нам не нужно придумывать дополнительные механизмы: мы просто транслируем данные из документа в регистр.
Однако при большом количестве измерений (более 10–15) мы сталкиваемся с серьезными техническими ограничениями СУБД. Каждое измерение — это поле, входящее в состав индексов. Рассмотрим, к чему это приводит:
INSERT в таблицы итогов и движений).Организация (где всего 2 значения), а вторым — Номенклатура (где 100 000 значений), то запрос остатков только по номенклатуре будет крайне медленным, так как СУБД придется сканировать весь индекс.Этот вариант подходит только в том случае, если объем данных невелик (например, до нескольких тысяч записей в год) или если состав измерений всегда фиксирован в запросах.
Разберем более современный подход, который активно применяется в типовых конфигурациях последнего поколения. Вместо того чтобы создавать 20 измерений в регистре, мы создаем всего одно измерение — КлючАналитики. Это ссылка на справочник, в реквизитах которого хранятся все наши разрезы (склад, статья, подразделение и т.д.).
Как это работает на практике:
Перед записью движений программный код проверяет, существует ли в справочнике комбинация параметров, указанная в документе. Если существует — берется ссылка на готовый элемент. Если нет — создается новый элемент справочника.
Рассмотрим пример кода для поиска или создания ключа аналитики:
Функция ПолучитьКлючАналитики(СтруктураПараметров)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Ссылка
|ИЗ Справочник.КлючиАналитикиУчетаНоменклатуры
|ГДЕ Номенклатура = &Номенклатура
| И Склад = &Склад
| И Статья = &Статья";
Запрос.УстановитьПараметр("Номенклатура", СтруктураПараметров.Номенклатура);
Запрос.УстановитьПараметр("Склад", СтруктураПараметров.Склад);
Запрос.УстановитьПараметр("Статья", СтруктураПараметров.Статья);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка;
Иначе
НовыйКлюч = Справочники.КлючиАналитикиУчетаНоменклатуры.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(НовыйКлюч, СтруктураПараметров);
НовыйКлюч.Записать();
Возврат НовыйКлюч.Ссылка;
КонецЕсли;
КонецФункции
Преимущества этого метода:
Недостатки: данный метод сложен в поддержке. Как отмечалось в обсуждении, обычный пользователь не понимает, что такое «Ключ аналитики», и при возникновении ошибок (например, задублировались ключи или неверно сформировались) техподдержке будет гораздо сложнее разобраться в причинах.
Проанализируем ситуацию: действительно ли нам нужны остатки по всем 20 реквизитам? Зачастую для оперативного контроля при проведении документа нам достаточно знать остаток в разрезе Номенклатура, Склад и Характеристика. А такие данные, как Менеджер, Статья движения или Подразделение, нужны только для отчетов об оборотах за месяц.
В этом случае оптимальным решением будет создание двух регистров:
Номенклатура и Склад). Это обеспечивает мгновенное проведение документа.Рассмотрим, как это реализовать. В документе при проведении мы делаем записи в оба регистра. При построении отчета «Остатки и обороты» мы соединяем данные: остатки берем из оперативного регистра, а детальную аналитику движений — из оборотного.
Выясним, как сделать так, чтобы даже «широкий» регистр работал быстрее. Если вы все же решили использовать один регистр с кучей измерений, следуйте правилу селективности:
Первыми в списке измерений в конфигураторе должны идти те поля, которые:
Важный момент: Если вы создаете запрос к виртуальной таблице Остатки, всегда старайтесь передавать в параметры условия по первым измерениям регистра. Если пропустить первое измерение и наложить фильтр только по второму, платформа не сможет эффективно использовать индекс (произойдет Index Scan вместо Index Seek).
Для высоконагруженных систем обязательно включайте свойство регистра «Разделить итоги». Это позволяет платформе записывать данные не в одну строку таблицы итогов, а в несколько параллельных «веток» (разделителей). Это критически важно, когда сотни пользователей одновременно списывают один и тот же товар с одного склада. Без разделителя итогов они выстроятся в очередь, ожидая разблокировки одной строки в базе данных. С разделителем — записи пройдут параллельно.
Подведем итог нашему анализу. Выбор структуры регистра зависит от планируемой нагрузки:
Левое Соединение.Проектирование регистров — это всегда баланс между скоростью записи, скоростью чтения и простотой поддержки. Тщательный анализ требований к отчетам на этапе проектирования позволит избежать дорогостоящей переработки архитектуры в будущем.