Может ли тяжелый отчет повредить базу 1С и как правильно посчитать количество покупателей товара

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с крупными информационными базами нередко возникает соблазн сформировать всеобъемлющую «шахматку» — кросс-таблицу, содержащую в строках весь ассортимент номенклатуры, а в столбцах всех контрагентов предприятия. Разберем, к каким последствиям для серверной базы 1С приводит запуск отчета размером в десятки тысяч строк и тысячи колонок, может ли такая операция физически повредить данные и как решить прикладную задачу оптимизированными средствами платформы.

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

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

  1. Переполнение дискового пространства СУБД. При сложной сортировке, группировке или соединении огромных массивов данных сервер баз данных активно задействует временное хранилище (в Microsoft SQL Server это база tempdb). Если объем промежуточных вычислений исчерпает свободное место на диске, СУБД аварийно остановит обработку транзакций, из-за чего база может перейти в состояние сбоя (Recovery Pending или Suspect), став недоступной для пользователей.
  2. Блокировки таблиц. Если в СУБД не активирован механизм версионирования строк (Read Committed Snapshot Isolation — RCSI), длительный запрос на чтение накладывает разделяемые блокировки (Shared locks). В результате пользователи не могут проводить новые документы по регистрам, которые в этот момент непрерывно сканируются отчетом.
  3. Аварийный сброс рабочего процесса rphost. Серверный процесс 1С rphost собирает данные запроса в оперативной памяти. При превышении доступного объема ОЗУ (особенно если используется 32-разрядный сервер 1С с лимитом около 2–3 ГБ на процесс) рабочий процесс аварийно завершается операционной системой. Это приводит к падению сеансов всех пользователей, работавших на этом процессе, и потере их несохраненных данных.

Ограничения табличного документа платформы 1С

Выясним причину, почему вывод отчета размером 30 000 строк на 2 500 столбцов заведомо обречен на провал на стороне клиента. Матрица таких габаритов содержит 75 000 000 ячеек. Объект платформы ТабличныйДокумент хранит в оперативной памяти свойства каждой отдельной ячейки: форматирование, цвет, границы, текст и параметры шрифта.

Даже при минимальном расходе памяти около 50 байт на ячейку только для формирования экранной формы потребуется более 3,5–4 ГБ непрерывной оперативной памяти клиентского приложения. Кроме того, исчерпываются системные дескрипторы графического интерфейса Windows (GDI handles). В результате пользовательский сеанс 1С завершится аварийно с системным сообщением «Недостаточно памяти» задолго до окончания отрисовки таблицы.

Подход, при котором строится гигантская пустая матрица только ради того, чтобы выгрузить ее в Excel и посчитать заполненные ячейки формулой СЧЕТЗ, является грубой архитектурной ошибкой. Всю аналитическую обработку должна выполнять СУБД на уровне запроса.

Оптимальное решение: расчет уникальных клиентов через язык запросов 1С

Рассмотрим реальную цель: выяснить показатель дистрибьюции — сколько именно различных контрагентов покупали ту или иную номенклатурную позицию за указанный интервал времени. Нам не требуется выводить имена покупателей в колонки; нам нужно получить конечное число клиентов для каждой строки номенклатуры.

Для решения этой задачи достаточно применить агрегатную функцию языка запросов КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) с группировкой по номенклатуре. Посмотрим на пример запроса, выполняющего этот расчет на уровне регистра накопления Продажи в конфигурации «Управление торговлей 10.3»:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ПродажиОбороты.ДоговорКонтрагента.Владелец) КАК КоличествоПокупателей
ИЗ
    РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаОкончания, , ) КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
    ПродажиОбороты.Номенклатура

Разберем по шагам, как работает этот алгоритм:

  1. Обращение происходит к виртуальной таблице РегистрНакопления.Продажи.Обороты, которая уже содержит предварительно рассчитанные итоги, что значительно ускоряет выборку.
  2. Поле ДоговорКонтрагента.Владелец указывает непосредственно на справочник Контрагенты, то есть на конкретного покупателя.
  3. Конструкция КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) выполняет агрегацию на стороне СУБД. Если клиент «Васильев» покупал «Кроссовки красные» двадцать раз по разным накладным, СУБД учтет его строго один раз.
  4. Предложение СГРУППИРОВАТЬ ПО сворачивает весь массив до двух простых колонок: номенклатура и число уникальных клиентов. Вместо 75 миллионов ячеек на клиент возвращается легкая линейная таблица из 30 000 строк.

Этот запрос можно вставить в стандартную обработку Консоль отчетов или Консоль запросов и мгновенно получить готовый результат без зависания системы.

Реализация расчета через Систему компоновки данных (СКД)

Рассмотрим вариант реализации аналогичного отчета через Систему компоновки данных (СКД), который позволяет гибко накладывать отборы и настраивать оформление:

  1. Создадим новый отчет и откроем его основную схему компоновки данных.
  2. Добавим набор данных — запрос, выбрав поля Номенклатура и ДоговорКонтрагента.Владелец из таблицы оборотов регистра Продажи.
  3. Перейдем на вкладку «Ресурсы» и добавим расчетное поле. В качестве выражения укажем: Количество(Различные ДоговорКонтрагентаВладелец).
  4. На вкладке «Настройки» в структуру отчета добавим обычную группировку по полю Номенклатура. В выбранные поля включим саму номенклатуру и созданный ресурс.

В результате платформа сформирует компактную таблицу с минимальным потреблением оперативной памяти и нулевым риском перегрузки кластера серверов 1С.

Защита серверной базы от зависания тяжелых отчетов

Проанализируем системные меры, которые администратор 1С должен предпринять для предотвращения падений кластера из-за случайного запуска тяжелых выборок пользователями:

  1. Настройка параметров рабочего сервера 1С. В консоли администрирования кластера серверов 1С для рабочего сервера следует задать параметры: Максимальный объем памяти рабочих процессов и Безопасный расход памяти за один вызов. При их превышении сервер корректно прервет исполнение прожорливого вызова без аварийного падения службы rphost.
  2. Фоновое формирование отчетов. Формирование объемных отчетов необходимо выполнять в фоновом задании. Это освобождает клиентский интерфейс и позволяет пользователю отменить длительный процесс при необходимости.
← На главную