Установили заказчику новую систему. Внедренцы заметили, что иногда поиск грузит процессор под 100% и работает очень долго (по 5-9 секунд). При этом записей в базе данных еще немного. Настроив log_min_duration_statement на 5 секунд, мы получили пример тормозящего запроса. Можно сказать, что он огромный: с чтением почти десятка вьюшек, множеством условий и подзапросов. Для эксперимента залили дамп этой базы на другой сервер и там тормозящий запрос выполнился примерно за 150-170 миллисекунд. Версия PostgreSQL на серверах совпадала (16.6). Разница была в том, что на боевом сервере установлен Debian, а на тестовом MS Windows. Дальше – "веселее". Залили дамп на новую виртуальную машину с Debian – запрос тормозит, залили дамп на виртуальную машину с ALT Linux – запрос тормозит...
Танцы с бубном у сервера указали на виновника. Им оказалась JIT-компиляция. Согласно документации:
JIT-компиляция (Just-In-Time compilation, Компиляция "точно в нужное время") – это производимая во время выполнения процедура преобразования интерпретируемого варианта исполнения программы в программу на языке процессора. Например, вместо использования универсального кода, способного вычислять произвольные SQL-выражения, для вычисления конкретного условия WHERE a.col = 3 можно сгенерировать функцию, предназначенную именно для этого выражения, которую сможет выполнять непосредственно процессор, так что она будет выполняться быстрее.
JIT-компиляция имеет смысл в первую очередь для длительных запросов, нагружающих процессор. Например, такой характер обычно имеют аналитические запросы. Для быстрых запросов накладные расходы, связанные с выполнением JIT-компиляции, часто будут превышать выигрыш от их ускорения.
В настоящее время реализация JIT в PostgreSQL поддерживает ускорение вычисления выражений и преобразования кортежей. В будущем могут быть ускорены и некоторые другие операции.
Приведу кусочки планов выполнения запроса на тестовом стенде с Debian:
- с включенной JIT-компиляцией (set jit = on):
По Options видно, что JIT используется по полной: встраивание (Inlining), оптимизация (Optimization), компиляция выражений (Expressions) и преобразование кортежей (Deforming) – все в truePlanning Time: 31.450 ms JIT: Functions: 1334 Options: Inlining true, Optimization true, Expressions true, Deforming true Timing: Generation 40.489 ms, Inlining 70.353 ms, Optimization 2892.635 ms, Emission 2222.264 ms, Total 5225.741 ms Execution Time: 5405.239 ms
- с выключенной JIT-компиляцией (set jit = off) или с выключенной JIT-компиляцией выражений (set jit_expressions = off):
Planning Time: 18.681 ms Execution Time: 139.740 ms
При отказе от JIT-компиляции мы наблюдаем ускорение выполнения запроса почти в 40 раз!
Сообщение в коммите к PostgreSQL 11: "There's a substantial risk that the JIT feature has bugs - it was largely written by a single person (i.e. me), nontrivial and there definitely have been features that have been more widely reviewed.".
Комментариев нет:
Отправить комментарий