Використання параметра Умова під час звернення до віртуальної таблиці
Використання складних конструкцій у параметрі Умова під час звернення до віртуальної таблиці призводить до повільної роботи запиту.Проблема. Пояснення. Рекомендація
Проблема
Використання складних конструкцій у параметрі Умова під час звернення до віртуальної таблиці призводить до повільної роботи запиту.
Пояснення
Віртуальна таблиця — це зручна річ для звернення до даних регістру. Віртуальна таблиця приховує подробиці своєї роботи, надаючи зрозумілий спосіб звернення до даних. Зокрема, віртуальна таблиця по-різному формує запити до бази даних залежно від того, який режим роботи має регістр (чи увімкнено зберігання актуальних підсумків, чи розраховано підсумки та на який останній період). Вона може як використовувати тимчасові таблиці бази даних, так і сформувати підзапит.
Параметр Умова призначений для того, щоб скоротити обсяг даних, що обробляється під час роботи віртуальної таблиці. Важливо розуміти, що під час використання тимчасової таблиці жоден оптимізатор СУБД не зможе розпізнати, що з тимчасової таблиці надалі буде використано лише частину даних, а отже без правильного зазначення параметра Умова заповнення тимчасової таблиці непотрібними даними часто може бути причиною проблем із продуктивністю.
З іншого боку, якщо в параметр Умова закласти забагато, то такий підхід також може принести більше проблем, ніж користі.
Під час розбору однієї з проблем продуктивності в конфігурації було виявлено запит до віртуальної таблиці регістру, при цьому в параметрі Умова було зазначено вираз із підзапитом і з'єднаннями двох табличних частин. Ба більше, через використання неявних з'єднань (використання виразу через крапку у виразі мови запитів) кількість таблиць у цьому виразі зросла ще більше. Це призвело до негативного результату — замість збільшення продуктивності вийшло зменшення швидкості роботи.
Рекомендація
Під час звернення до віртуальної таблиці слід передавати в умови найпростіші конструкції, наприклад, "Вимір = Значення". Не рекомендується використовувати підзапити та з'єднання(*) у параметрах віртуальної таблиці, оскільки це призводить до повільної роботи запиту.
(*) Примітка. Як явні з'єднання в підзапитах, так і неявні — під час звернення до полів "через крапку" від посилання та з'єднання, що додаються з обмежень доступу до даних (RLS), передбачених у ролях конфігурації.
Якщо все ж без підзапитів не обійтися, то рекомендується дотримуватися таких умов:
- у підзапиті лише одна таблиця, немає з'єднань з іншими таблицями;
- якщо в підзапиті таблиця табличної частини (наприклад, Документ.Накладна.СписокТоваров), то не повинно бути звернення до реквізитів таблиці-шапки (Накладна.Проведен);
- якщо в підзапиті таблиця, яка може мати табличні частини (наприклад, Документ.Накладна), то не повинно бути звернень до табличних частин (наприклад, ГДЕ Документ.Накладна.СписокТоваров.Номенклатура = "1");
- якщо в підзапиті тимчасова таблиця, то не повинно бути умов (розділу ГДЕ);
- якщо в підзапиті постійна таблиця, то умова (розділ ГДЕ) може бути допустимою, лише якщо умова виконується для 80% (або більше) випадків; відсутність умови означає виконання для 100% випадків;
- якщо в підзапиті постійна таблиця, то в обмеженнях доступу до даних (RLS) не повинно міститися підзапитів і з'єднань (допускаються лише прості умови виду "ГДЕ Реквизит = Значение", "ГДЕ Истина").
Наприклад, неправильно:
... ИЗ РегистрНакопления.ТоварыКОтгрузке.Остатки(&ДатаОтгрузки,&ОтображениеРаспоряжений И ДокументОтгрузки.Склад = &Склад // неявне з'єднання «через крапку» ИЛИ ДокументОтгрузки В (ВЫБРАТЬ // підзапит зі з'єднанням Распоряжения.Распоряжение КАК ДокументОтгрузки ИЗ Документ.ЗаданиеНаПеревозку.Распоряжения КАК Распоряжения // доступ до цього документа обмежено складним RLS, який неявно додає ще пару з'єднань ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаданиеНаПеревозку.СкладыПогрузки КАК СкладыПогрузки ПО Распоряжения.Ссылка = СкладыПогрузки.Ссылка И СкладыПогрузки.Склад = &Склад И Распоряжения.Ссылка.Проведен // тут і нижче звернення до реквізитів шапки И Распоряжения.Ссылка.Статус В (...)) )
Правильно:
... ИЗ РегистрНакопления.ТоварыКОтгрузке.Остатки( &ДатаОтгрузки, Склад = &Склад // тепер це вимір регістру ИЛИ ДокументОтгрузки В (ВЫБРАТЬ ЗаданияНаПеревозку.Распоряжение ИЗ ВТЗаданияНаПеревозку КАК ЗаданияНаПеревозку)) // вибірка з тимчасової таблиці без умов
У разі, якщо потрібно використовувати кілька умов із підзапитами, слід вибрати одну, що задовольняє умовам вище та відфільтровує максимальну кількість записів. Решту умов слід накладати на зовнішній запит.