Почему зависает открытие справочника Банковские счета при выборе из документов в 1С 7.7 SQL?

Программист 1С v7.7 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При переносе информационных баз 1С:Предприятия 7.7 на клиент-серверный вариант (MS SQL Server) разработчики и системные администраторы нередко сталкиваются с ситуацией, когда открытие компактного справочника для выбора значения занимает от нескольких секунд до десятков секунд. Особенно ярко это проявляется при интерактивном вызове формы списка из документов или констант в терминальном режиме. Разберем по шагам, почему возникает эта задержка и как ее устранить.

Анализ кода и локализация проблемы

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


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

Выясним причину задержки. Если закомментировать строку с вызовом метода НайтиЭлемент(), форма списка открывается практически мгновенно. Однако при наличии предварительного поиска открытие списка замирает на несколько секунд. Замер производительности при этом показывает основное время ожидания именно на строке с методом Выбрать().

Особенности механизма серверных курсоров в 1С 7.7 SQL

Проанализируем, как платформа 1С 7.7 взаимодействует с MS SQL Server в обоих случаях:

  1. Открытие без предварительного позиционирования: Платформа запрашивает у СУБД первую порцию видимых на экране строк с начала таблицы. Выполняется простой и быстрый запрос, возвращающий первые N записей.
  2. Открытие с предварительно найденным элементом: Метод НайтиЭлемент() переводит внутренний контекст объекта на конкретную запись. Когда следом вызывается метод Выбрать("...", "ФормаСписка"), платформа пытается отобразить список так, чтобы найденный элемент сразу оказался в фокусе и в видимой области окна. Для этого через ODBC-драйвер задействуются API-курсоры СУБД (вызовы процедур sp_cursoropen и sp_cursorfetch). СУБД вынуждена рассчитывать относительное смещение бегунка полосы прокрутки и выбирать строки как выше, так и ниже текущей позиции. При неоптимальных индексах или особенностях сетевого стека это приводит к сканированию всей таблицы.
  3. Проблема связанных данных (N+1 запросов): Если в форме списка выводятся реквизиты других справочников (например, колонка Банк с типом ссылки на справочник «Банки»), для каждой отображаемой строки курсора платформа выполняет отдельный SQL-запрос за наименованием банка.

Способ 1. Замена формы списка на выбор из СпискаЗначений

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

Посмотрим на пример переписанного фрагмента кода:


СписокСчетов = СоздатьОбъект("СписокЗначений");
СпрСчета = СоздатьОбъект("Справочник.БанковскиеСчета");

// Инициализируем выборку счетов
СпрСчета.ВыбратьЭлементы();
Пока СпрСчета.ПолучитьЭлемент() = 1 Цикл
    // Формируем понятное текстовое представление для выбора
    Представление = СокрЛП(СпрСчета.НомерСчета) + " (" + СокрЛП(СпрСчета.Банк.Наименование) + ")";
    СписокСчетов.ДобавитьЗначение(СпрСчета.ТекущийЭлемент(), Представление);
КонецЦикла;

ВыбЗначение = Конт.РасчетныйСчет;
Если СписокСчетов.ВыбратьЗначение(ВыбЗначение, "Укажите расчетный счет", , , 2) = 1 Тогда
    Конт.РасчетныйСчет = ВыбЗначение;
КонецЕсли;

В этом варианте данные считываются последовательной быстрой выборкой без создания оконных таблиц и серверных курсоров. Метод ВыбратьЗначение() отображает легкое модальное окно, в котором сразу подсвечивается текущее значение, переданное в переменную ВыбЗначение.

Способ 2. Настройка сетевых протоколов SQL-клиента

Если терминальный сервер и сервер баз данных разнесены по разным машинам или работают под управлением устаревших версий операционных систем (например, Windows Server 2003), задержки при вызове курсоров часто связаны с протоколами именованных каналов.

  1. Запустите на клиентской (или терминальной) машине утилиту настройки сетевого клиента SQL: cliconfg.exe.
  2. Перейдите на вкладку General (Общие) и убедитесь, что протокол TCP/IP имеет наивысший приоритет над протоколом Named Pipes.
  3. Если сервер 1С и MS SQL Server физически работают на одном и том же компьютере, включите протокол Shared Memory (Общая память), что полностью исключит накладные расходы сетевого стека.
  4. На вкладке Alias (Псевдонимы) создайте явный псевдоним сервера с указанием прямого IP-адреса и фиксированного порта (по умолчанию 1433), чтобы исключить паузы на разрешение имен NetBIOS.

Способ 3. Отключение аппаратной разгрузки сети (Chimney Offload)

В серверных ОС Windows Server 2003 SP2 и ранних выпусках Windows Server 2008 причиной микрозадержек на 2–5 секунд при передаче множества мелких пакетов часто выступает пакет Scalable Networking Pack (SNP).

Для устранения конфликтов сетевого драйвера с СУБД отключите разгрузку TCP через командную строку, запущенную от имени администратора:

netsh int ip set chimney DISABLED

После отключения аппаратного ускорения обработка потока мелких запросов ODBC курсора нормализуется.

Особенности работы платформы 1С 7.7 на современных версиях Windows Server

Перевод базы на современные операционные системы (Windows Server 2012 и выше) и новые версии MS SQL Server устраняет проблемы сетевого стека прошлых лет, но требует учета системных ограничений платформы 1С 7.7:

  1. Ошибка порядка сортировки базы данных: При подключении к новым версиям MS SQL Server платформа может выдать ошибку несоответствия кодовой страницы. Для обхода проверки в каталог исполняемых файлов платформы BIN добавляют пустой файл-маркер ORDNoChk.prm.
  2. Параллелизм запросов (Max Degree of Parallelism): В свойствах экземпляра SQL Server необходимо принудительно задать параметр Max Degree of Parallelism = 1. Если этого не сделать, попытки оптимизатора СУБД распараллелить старые запросы 1С 7.7 будут приводить к частым взаимным блокировкам (дедлокам).
  3. Предотвращение выполнения данных (DEP): В свойствах системы Windows Server исполняемый файл 1cv7s.exe необходимо внести в список исключений DEP во избежание внезапных падений программы при работе пользователей.
← На главную