При работе в крупных торговых сетях с распределенными информационными базами (РИБ) администраторы и разработчики часто сталкиваются с проблемой производительности. Типичная ситуация: необходимо назначить скидку на весь ассортимент (например, 40 000 позиций), за исключением небольшой группы товаров (например, 1 000 позиций). Если создавать стандартный сегмент на 39 000 товаров, то регистр СоставСегментовНоменклатуры раздувается до огромных размеров, и его миграция по 50 узлам РИБ превращается в «ад», как выразился автор темы. Рассмотрим, как решить эту задачу изящно, используя «инверсный» подход: когда мы создаем сегмент исключений и заставляем скидку работать «от противного».
Прежде чем мы перейдем к решениям, разберем, почему стандартный подход не всегда эффективен. В программе 1С:Розница сегменты номенклатуры могут быть статическими или динамическими. Состав статического сегмента хранится в физической таблице. При каждом изменении состава или создании нового сегмента сотни тысяч записей должны улететь в каждый магазин. Это забивает каналы связи, раздувает объем баз на точках и замедляет расчеты в РМК. Инверсия сегмента позволяет нам передавать только 1 000 товаров-исключений вместо 39 000 основных, что сокращает трафик в десятки раз.
Проанализируем наиболее гибкий и современный метод — использование механизма внешних обработок. Этот метод хорош тем, что нам не нужно вносить изменения в основную конфигурацию или расширение, ломая типовые запросы. Мы создаем условие как отдельный объект.
Рассмотрим алгоритм реализации:
ДополнительныеОтчетыИОбработки.РассчитатьУсловие() или аналогичная в зависимости от версии БСП).Пример программной логики внутри обработки может выглядеть следующим образом:
// Пример логики проверки вхождения в сегмент "от обратного"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| 1
|ИЗ
| РегистрСведений.НоменклатураСегмента КАК НомСегмента
|ГДЕ
| НомСегмента.Номенклатура = &Номенклатура
| И НомСегмента.Сегмент = &СегментИсключение";
Запрос.УстановитьПараметр("Номенклатура", ТекущийТовар);
Запрос.УстановитьПараметр("СегментИсключение", СсылкаНаСегментИсключений);
Результат = Запрос.Выполнить();
// Если результат пустой, значит товара НЕТ в сегменте исключений - СКИДКА ПОЛОЖЕНА
Если Результат.Пустой() Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
Использование внешней обработки позволяет менеджеру просто выбрать это условие в маркетинговой акции, указать малый сегмент исключений, и система сама поймет, что на эти товары скидку давать не нужно, а на все остальные — нужно.
Выясним, как решить задачу стандартными средствами интерфейса, если вы не хотите писать код. В 1С:Розница существует мощный механизм совместного применения скидок. Мы можем настроить логику через группу с приоритетом Вытеснение.
Разберем этот метод по шагам:
Как это работает в РМК? Программа сначала проверяет скидки с самым высоким приоритетом. Если товар входит в сегмент исключений, срабатывает Скидка №1 (0%). Поскольку группа работает в режиме Вытеснения, поиск других скидок для этой строки чека прекращается. Если же товара нет в исключениях, система переходит к Скидке №2 и успешно применяет 15%. Результат достигнут: сегмент в базе маленький, а логика работает корректно.
Проанализируем альтернативный вариант, который еще легче для обмена данными, чем сегменты. Если товары-исключения можно сгруппировать по смыслу, используйте ЦеновыеГруппы. Информация о ценовой группе хранится непосредственно в реквизите справочника Номенклатура.
В настройках скидки в поле «Область предоставления» часто можно выбрать не только сегмент, но и конкретные ценовые группы. Если ваша конфигурация позволяет указать «Для всех товаров, кроме групп...», это будет самым быстрым техническим решением, так как оно вообще не использует тяжелые регистры сведений.
Посмотрим на ситуацию, в которой оказался автор темы: желание «подправить» глобальный запрос в общем модуле. Рассмотрим, почему это опасно:
НЕ В (ВЫБРАТЬ...) может привести к «зависанию» интерфейса кассира, так как SQL-серверу сложнее оптимизировать такие планы запросов, особенно если в таблицах есть NULL значения.Для решения задачи инверсии сегмента в 1С:Розница 2.2 мы рекомендуем придерживаться следующей иерархии решений:
Инверсия в расширение к справочнику СкидкиНаценки и аккуратно внедрите его в механизм расчета, не трогая основную конфигурацию.Помните, что главная цель — минимизировать объем данных, передаваемых через РИБ. Использование сегмента исключений на 1 000 позиций вместо основного сегмента на 35 000 — это правильный архитектурный ход, который сэкономит ресурсы серверов и нервы системных администраторов.