Оптимизация: неэффективные запросы

13.06.19

Разработка - Запросы

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

Пример №1

"ВЫБРАТЬ 
... ИЗ ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ... ИЗ)"

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

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

Пример 2

Отсутствие параметров в виртуальных таблицах и вложенных запросах.

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

Следует отметить, что на экзаменах за такое грубое допущение может существенно снизится оценка. 

"Но ведь все работает и так!" - спросят многие. Да, действительно, выполнив запрос, соединив его после левым соединением с нужным нам запросом, СУБД безусловно отбросит все лишние записи. Но это произойдет потом, а вначале она варварски заблокирует всю таблицу. А если это какой-то распухший и важный как Масленица регистр, ну, скажем, ОстаткиТоваров? А если у нас 100 пользователей одновременно работают в 1С и каждый в той или иной степени вынужден обращаться к данному регистру?

Думаю, тут все понятно.

Пример 3

Индексы и условия запроса.

Использование неиндексируемых полей в условиях запроса приводит к избыточному чтению данных СУБД и, как следствие, захвату гораздо большего количества записей, чем необходимо. Каждая читаемая запись в СУБД блокируется для чтения. 

Пример 4

Наверное, самый распространенный. По крайней мере, я частенько с ним сталкивался на практике.

"ВЫБРАТЬ
        Контрагенты.ОсновнойДоговор.Ссылка КАК ОсновнойДоговор
ИЗ
        Справочник.Контрагенты
ГДЕ
        Контрагенты.Родитель.Ссылка = &ТакиеТоКонтрагенты"

Казалось бы, чего тут такого - запрос как запрос. Ну подумаешь, дописываем мы везде, где в голову взбредет через точку Ссылка, чего тут такого? Зато - так нагляднее!

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

Проведем аналогию с яблоками: в магазине, если вы хотите купить одно яблоко, и вы знаете, что оно лежит в верхней раскрытой коробке, лежит на самом верху, вы не будете для этого вынимать все коробки с яблоками, потрошить их и раскладывать яблочки по одному, сравнивая их, пока не дойдете до нужной коробки и не выберете свое яблоко. Вы посмотрите несколько в той, что наверху, распакована и содержит уже подходящие вам яблоки. Так же и в СУБД: при обращении в запросе к полям таблицы через точку - вы заставляете систему строить подзапрос к таблице поля. 

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

Это значит тормоза, подвисания, а в некоторых случаях неразрешимые конфликты блокировок, одна из жертв которых может прибежать к вам или к вашему начальнику в панике со словами "Все пропало".

Чтобы этого избежать, следует всегда помнить о главном правиле при построении запросов:

Все записи, которых коснется СУБД, будут заблокированы

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Руководитель проекта Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Платные (руб)

Инструменты для разработчиков 1С 8.3: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.

12000 руб.

02.09.2020    169274    937    403    

905

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    11394    sergey279    18    

65

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    6338    XilDen    36    

83

Запросы Программист Запросы Бесплатно (free)

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

16.08.2024    9068    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2727    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

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

15.05.2024    10219    implecs_team    6    

48

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3623    andrey_sag    10    

38