Почему тормозит журнал банковских выписок в 1С 8.2 БП 2.0 и как это исправить?

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При работе с файловыми базами данных «1С:Предприятие 8.2» на конфигурации «Бухгалтерия предприятия 2.0» пользователи часто сталкиваются с резким падением производительности. Характерный симптом: при открытии, проведении или записи банковских документов система «зависает» на несколько секунд, а сетевой трафик между клиентским компьютером и сервером возрастает до предела. Особенно остро эта проблема проявляется при увеличении объема базы данных (более 1 Гб) и росте аналитики по субконто.

В этой статье мы подробно разберем причины возникновения таких зависаний, проанализируем поведение СУБД и файловой системы при работе по сети, а также рассмотрим практические способы оптимизации кода и инфраструктуры для восстановления быстродействия системы.

Шаг 1. Локализация проблемы с помощью замера производительности

Для того чтобы понять, почему база данных зависает на 5–8 секунд при работе с банковскими выписками, выполним замер производительности в отладчике «1С:Предприятия». Проанализировав технологический журнал и результаты замера, мы увидим, что основное время выполнения уходит на работу формы списка журнала документов БанковскиеВыписки.

Аномально долго выполняется типовая функция ПолучитьИтоги(ТекДата, ТекБанковскийСчет), которая призвана динамически рассчитывать остатки и обороты на выбранную пользователем дату по конкретному расчетному счету. При скроллинге журнала или переходе с одного дня на другой эта функция вызывается повторно, заставляя интерфейс полностью «замирать».

Шаг 2. Анализ узкого места в типовом запросе

Рассмотрим исходный текст запроса функции ПолучитьИтоги, который поставляется в типовой конфигурации:


Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
|	ВЫБОР
|		КОГДА БанковскиеСчета.ВалютаДенежныхСредств = &ВалютаРеглУчета
|			ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстаток
|		ИНАЧЕ ХозрасчетныйОстаткиИОбороты.ВалютнаяСуммаНачальныйОстаток
|	КОНЕЦ КАК НачальныйОстаток,
|	ВЫБОР
|		КОГДА БанковскиеСчета.ВалютаДенежныхСредств = &ВалютаРеглУчета
|			ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаОборотДт
|		ИНАЧЕ ХозрасчетныйОстаткиИОбороты.ВалютнаяСуммаОборотДт
|	КОНЕЦ КАК ВсегоПоступило,
|	ВЫБОР
|		КОГДА БанковскиеСчета.ВалютаДенежныхСредств = &ВалютаРеглУчета
|			ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаОборотКт
|		ИНАЧЕ ХозрасчетныйОстаткиИОбороты.ВалютнаяСуммаОборотКт
|	КОНЕЦ КАК ВсегоСписано,
|	ВЫБОР
|		КОГДА БанковскиеСчета.ВалютаДенежныхСредств = &ВалютаРеглУчета
|			ТОГДА ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстаток
|		ИНАЧЕ ХозрасчетныйОстаткиИОбороты.ВалютнаяСуммаКонечныйОстаток
|	КОНЕЦ КАК КонечныйОстаток
|ИЗ
|	РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(
|			НАЧАЛОПЕРИОДА(&ДатаИтогов, ДЕНЬ),
|			КОНЕЦПЕРИОДА(&ДатаИтогов, ДЕНЬ),
|			,
|			ДвиженияИГраницыПериода,
|			,
|			ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.БанковскиеСчета),
|			Организация = &Организация
|				И Субконто1 = &БанковскийСчетИтогов) КАК ХозрасчетныйОстаткиИОбороты
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.БанковскиеСчета КАК БанковскиеСчета
|		ПО ХозрасчетныйОстаткиИОбороты.Subkonto1 = БанковскиеСчета.Ссылка
|ГДЕ
|	БанковскиеСчета.Ссылка = &БанковскийСчетИтогов";

Проанализируем параметры виртуальной таблицы РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты. Мы видим, что в качестве параметров отбора передаются Организация и значение субконто (Субконто1 = &БанковскийСчетИтогов). Однако параметр Счет в условиях виртуальной таблицы полностью отсутствует!

С точки зрения СУБД (как файлового движка .1CD, так и внешних СУБД вроде MS SQL или PostgreSQL), это критическая ошибка построения запроса по следующим причинам:

  1. Использование составных индексов: Таблицы итогов регистра бухгалтерии имеют индексы, в которых поле Счет (_AccountRRef) идет первым. Если в запросе не указан конкретный счет (например, 51 «Расчетные счета» или 52 «Валютные счета»), СУБД не может выполнить быстрое позиционирование по индексу (операцию Index Seek).
  2. Сканирование всей таблицы (Index Scan): Вместо точечного поиска СУБД вынуждена сканировать весь индекс или всю таблицу итогов, чтобы сопоставить переданное субконто (которое к тому же имеет составной тип данных) со значениями в базе.
  3. Рост объема данных: Если в базе ведется детальный аналитический учет (много субконто, контрагентов, договоров), таблицы РегистрБухгалтерии.Хозрасчетный и РегистрБухгалтерии.Хозрасчетный.ИтогиПоСчетамССубконто разрастаются до огромных размеров. Полное сканирование таких таблиц при каждом открытии выписки парализует работу СУБД.

Шаг 3. Оптимизация запроса в коде конфигурации

Для устранения этой проблемы нам необходимо жестко ограничить выборку виртуальной таблицы конкретным счетом учета. Для этого отредактируем функцию ПолучитьИтоги. Мы добавим в параметры виртуальной таблицы отбор по счету Счет.Ссылка = &СчетБанк. Передаваемое значение мы будем получать из текущей строки журнала документов.

Рассмотрим оптимизированный вариант функции:


Функция ПолучитьИтоги(ТекДата, ТекБанковскийСчет)

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

	Запрос.УстановитьПараметр("ДатаИтогов", ТекДата);
	Запрос.УстановитьПараметр("БанковскийСчетИтогов", ТекБанковскийСчет);
	
	// Передаем счет учета из текущей строки журнала документов
	Попытка
		ТекущийСчетУчета = ЭлементыФормы.ЖурналДокументовСписок.ТекущаяСтрока.СчетБанк;
	Исключение
		ТекущийСчетУчета = ПланыСчетов.Хозрасчетный.РасчетныеСчета;
	КонецПопытки;
	
	Запрос.УстановитьПараметр("СчетБанк", ТекущийСчетУчета);
	Запрос.УстановитьПараметр("Организация", ТекБанковскийСчет.Владелец);
	Запрос.УстановитьПараметр("ВалютаРеглУчета", мВалютаРегламентированногоУчета);

	ТаблицаИтогов = Запрос.Выполнить.Выгрузить;
	Возврат ТаблицаИтогов;

КонецФункции

Благодаря явному указанию параметра СчетБанк в условиях виртуальной таблицы, СУБД моментально отсекает лишние ветки индекса. Вместо сканирования миллионов записей система делает точечную выборку (Index Seek), снижая время выполнения запроса с 5 секунд до нескольких миллисекунд.

Шаг 4. Особенности сетевого обмена и блокировки файловой системы (SMB)

Почему при работе одного пользователя локально тормоза практически незаметны, а при подключении второго пользователя по сети 100 Мбит/с работа становится невозможной? Разберем физику этого процесса.

Когда с базой работает один пользователь, операционная система Windows применяет механизм **OpLocks (оппортунистических блокировок)**. Файл базы данных 1Cv8.1CD кэшируется в оперативной памяти клиентского ПК. Все тяжелые запросы выполняются внутри быстрой локальной памяти.

Как только к базе подключается **второй пользователь**, сетевой кэш принудительно отключается операционной системой во избежание повреждения структуры базы данных. С этого момента любой запрос начинает напрямую считывать бинарные страницы файла базы по сети. Неоптимальный запрос, выполняющий сканирование индексов, заставляет платформу прокачивать сотни мегабайт «сырых» данных. Сетевой адаптер 100 Мбит/с мгновенно утилизируется на 70-90%, создавая огромные задержки («очередь к диску» и сетевые коллизии).

Шаг 5. Проверка актуальности рассчитанных итогов

Еще одной неочевидной причиной медленной работы виртуальных таблиц является **неактуальность рассчитанных итогов регистра бухгалтерии**. Выясним, почему это происходит:

Шаг 6. Инфраструктурные рекомендации по устранению тормозов

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

  1. Переход в терминальный режим (RDP): Это самый дешевый и надежный способ ускорить файловую базу 1С. Мы размещаем базу локально на производительном сервере (желательно на SSD-накопителях), а пользователи подключаются к серверу через удаленный рабочий стол. При этом сетевой трафик передачи данных базы сводится к нулю, а по сети передается только картинка экрана.
  2. Использование клиент-серверного варианта (SQL/PostgreSQL): Если количество пользователей превышает 5–7 человек, файловый режим исчерпывает свои возможности блокировок. Перевод базы на MS SQL Server или бесплатный PostgreSQL позволит перенести все тяжелые расчеты на сторону сервера СУБД, а клиенты будут получать только готовый результат.
  3. Регулярное обслуживание базы данных: Необходимо систематически запускать процедуру «Тестирование и исправление» (ТиИ) с флагами «Реиндексация таблиц» и «Сжатие таблиц». Это устраняет фрагментацию индексов и уменьшает физический размер файла базы данных.

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

← На главную