При работе с большими таблицами документов (миллионы записей) пользователи нередко сталкиваются с задержками при постраничном листании списков клавишами Page Down или Page Up. Задержка в 1.5–2 секунды на каждую страницу делает интерактивную работу некомфортной, даже если сервер СУБД оснащен достаточным объемом оперативной памяти и быстрыми дисками SSD. Разберем детально механизм формирования запросов платформой 1С к MS SQL Server, выясним причины деградации производительности и рассмотрим способы устранения проблемы.
Проанализируем ситуацию: при просмотре трассировки в SQL Server Profiler фиксируются длительные запросы с выборкой первых строк (TOP). В тексте запроса, который платформа автоматически генерирует для позиционирования курсора списка, присутствует сложная конструкция с несколькими условиями OR:
SELECT TOP 48
_DocumentJournal7838_R._Date_Time AS _A1,
_DocumentJournal7838_R._Number AS _A2,
_DocumentJournal7838_R._Fld7841 AS _A3,
_DocumentJournal7838_R._DocumentTRef AS _A4TRef,
_DocumentJournal7838_R._DocumentRRef AS _A4RRef,
_DocumentJournal7838_R._Marked AS _A5,
_DocumentJournal7838_R._Posted AS _A6
FROM
_DocumentJournal7838 _DocumentJournal7838_R WITH(NOLOCK)
WHERE
_DocumentJournal7838_R._DocumentRRef > @P1 AND _DocumentJournal7838_R._Date_Time = @P2 AND _DocumentJournal7838_R._DocumentTRef = @P3 AND _DocumentJournal7838_R._Date_Time >= @P4 AND _DocumentJournal7838_R._Date_Time <= @P5 OR
_DocumentJournal7838_R._DocumentTRef > @P6 AND _DocumentJournal7838_R._Date_Time = @P7 AND _DocumentJournal7838_R._Date_Time >= @P8 AND _DocumentJournal7838_R._Date_Time <= @P9 OR
_DocumentJournal7838_R._Date_Time > @P10 AND _DocumentJournal7838_R._Date_Time >= @P11 AND _DocumentJournal7838_R._Date_Time <= @P12
ORDER BY
_DocumentJournal7838_R._Date_Time,
_DocumentJournal7838_R._DocumentTRef,
_DocumentJournal7838_R._DocumentRRef
Посмотрим на план выполнения этого запроса. В технологическом журнале и плане SQL Server операция отображается как Clustered Index Scan (сканирование кластерного индекса) вместо точечного поиска Clustered Index Seek:
OR не позволяет оптимизатору СУБД однозначно вычислить диапазон поиска для индексного поиска (Seek). В результате оптимизатор решает последовательно сканировать таблицу с начала диапазона в расчете на то, что условие TOP быстро прервет операцию.Выясним причину появления неоптимального SQL-кода. В старых версиях платформы 1С (в частности, в 8.1 и конфигурациях с установленным Режимом совместимости с версией 8.1) транслятор запросов списков формировал единый запрос со сложной дизъюнкцией для вычисления границ курсора.
Начиная с платформы 8.2 (без совместимости с 8.1) и во всех последующих версиях механизм позиционирования в обычных формах (ЖурналДокументовСписок, ДокументСписок) был переработан. Рассмотрим, как изменяется запрос после снятия режима совместимости:
SELECT TOP 43
T2._Date_Time,
T2._Fld7841,
T2._DocumentTRef,
T2._DocumentRRef,
T2._Marked,
T2._Posted
FROM _DocumentJournal7838 T2 WITH(NOLOCK)
WHERE ((T2._Date_Time >= @P1) AND (T2._Date_Time <= @P2)) AND T2._Date_Time = @P3 AND T2._DocumentTRef > @P4
ORDER BY (T2._Date_Time) ASC, (T2._DocumentTRef) ASC, (T2._DocumentRRef) ASC
OPTION (FAST 1)
Разберем ключевые изменения в новом плане:
OR позволяет СУБД использовать стандартный индекс по дате и ссылке для точечного позиционирования.OPTION (FAST 1) прямо предписывает оптимизатору SQL Server построить план, минимизирующий время возврата первых строк набора, исключая долгий просмотр таблиц.Если быстрое обновление режима совместимости невозможно по архитектурным причинам, применим сопутствующие методы ускорения работы со списками на СУБД:
НачалоИнтервала и КонецИнтервала жестко ограничивает блок WHERE по полю даты, предотвращая сканирование всей исторической глубины таблицы.Дата/Время + ТипДокумента + Ссылка. При установке пользовательской сортировки по другим колонкам (например, по номеру или контрагенту) СУБД вынуждена использовать некластерный индекс с операциями Key Lookup, что многократно увеличивает нагрузку на дисковую подсистему.DBCC FREEPROCCACHE временно устраняет влияние некорректного кэширования параметров.