Почему одинаковые SQL-запросы в 1С работают с разной скоростью на идентичных серверах и как это исправить?

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

В практике системного администрирования и разработки на платформе 1С:Предприятие часто встречается загадочная ситуация: два сервера с абсолютно идентичными характеристиками, одинаковыми версиями ОС и SQL Server показывают кратную разницу в производительности на одном и том же запросе. В одном случае тяжелый отчет выполняется за 0,6 секунды, а в другом — за 4,5 секунды. Давайте вместе проанализируем эту проблему, разберем причины возникновения таких аномалий и найдем способ оптимизации кода, который гарантирует стабильную скорость работы.

Поиск причин: почему «железо» и настройки SQL не всегда виноваты

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

  1. Версии SQL Server: Разница в несколько минорных сборок (например, 15.0.2093.5 против 15.0.2101.7) редко дает семикратный прирост. Проверка на контрольном стенде с разными версиями SQL часто показывает идентичные результаты, что исключает теорию «бага сборки».
  2. Дисковая подсистема: Хотя скорость чтения может различаться (например, 540 МБ/с против 380 МБ/с), для запросов, активно использующих процессор, эта разница нивелируется. Как показала практика, перенос виртуальных машин между узлами кластера дает выигрыш лишь в несколько миллисекунд, но не решает проблему секундных задержек.
  3. Настройки SQL Server: Параметры в sys.configurations (такие как Max Degree of Parallelism или Cost Threshold for Parallelism) должны быть идентичны. Но даже при полном совпадении настроек проблема может сохраняться.
  4. Статистика БД: Обновление статистики (UPDATE STATISTICS) — это обязательный шаг, но если планы запросов на «быстром» и «медленном» серверах «одинаковы до неприличия», значит, проблема кроется глубже — в механизме генерации этих планов самой платформой 1С.

Проанализируем ситуацию, когда база данных, перенесенная с «медленного» сервера на «быстрый», начинает работать так же медленно. Это доказывает, что корень проблемы — не в железе, а в данных и в том, как SQL Server интерпретирует запрос 1С для конкретного набора записей.

Разбор неоптимального запроса к регистру бухгалтерии

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


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

В данном примере используется фильтр по полям Субконто1 и Субконто2 через вложенный запрос из временной таблицы ВТ_ДанныеДляПодбораОплат. На первый взгляд запрос корректен, однако именно здесь кроется ловушка для оптимизатора SQL Server.

Почему важны «ВидыСубконто» в параметрах виртуальной таблицы

Выясним причину, по которой SQL Server может выбрать неоптимальный план. Регистры бухгалтерии в 1С имеют сложную структуру хранения итогов. Индексы в таблицах итогов построены по определенному набору полей: Период, Счет, РазделительИтогов, Организация и далее по порядку — Субконто1, Субконто2 и т.д.

Когда мы обращаемся к виртуальной таблице Остатки, не указывая параметр ВидыСубконто, платформа 1С генерирует сложный SQL-запрос, который пытается «угадать» типы данных в полях Субконто. Если в системе много планов счетов или сложная иерархия субконто, SQL Server может решить, что использование индекса по полям СубконтоN неэффективно, и перейдет к полному сканированию таблицы (Index Scan) вместо точечного поиска (Index Seek).

Важный технический нюанс: Для попадания в индекс необходимо соблюдать последовательность полей. Если вы делаете отбор по Субконто2, но не указали Субконто1, индекс может не сработать. Но даже если вы указали оба, отсутствие жесткого ограничения по типам (через ВидыСубконто) заставляет оптимизатор сомневаться в селективности запроса.

Решение проблемы: принудительное ограничение видов субконто

Рассмотрим исправленный вариант запроса, который позволил сократить время выполнения с 4 секунд до 0,5 секунды. Мы добавим в параметры виртуальной таблицы массив или список значений, содержащий конкретные виды субконто, по которым идет отбор (в нашем случае — «Контрагенты» и «Договоры»).


// Подготовим массив видов субконто для оптимизации индекса
ВидыСубконто = Новый Массив;
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты);
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры);

// Выполняем оптимизированный запрос
Запрос.УстановитьПараметр("ВидыСубконтоСчета62", ВидыСубконто);

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

После добавления этого параметра 1С формирует SQL-запрос с четким приведением типов JOIN к таблицам значений субконто. Это позволяет оптимизатору SQL Server однозначно определить, что использование индекса по Субконто1 и Субконто2 будет максимально эффективным.

Дополнительные факторы, влияющие на производительность ЦП

Если после оптимизации кода разница между серверами сохраняется, проанализируем настройки, которые влияют на выполнение запросов на уровне процессора в среде виртуализации:

Таким образом, мы выяснили, что кратная разница в производительности на «близнецах-серверах» чаще всего вызвана не аппаратными различиями, а нестабильностью планов запросов. Использование параметра ВидыСубконто в запросах к регистрам бухгалтерии является «лучшей практикой» (best practice), которая делает поведение оптимизатора SQL предсказуемым и гарантирует высокую скорость работы вне зависимости от того, на каком сервере развернута база данных.

← На главную