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

Публикация № 1076253

Администрирование - Оптимизация БД (HighLoad)

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

Пример №1

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

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

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

Пример 2

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

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

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

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

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

Пример 3

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

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

Пример 4

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

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

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

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

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

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

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

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

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

4

См. также

Специальные предложения

Автор запретил комментарии