Добавить в корзинуПозвонить
Найти в Дзене

Как я оптимизировал запрос в PostgreSQL

Пользователи облачного сервиса документооборота DamuBPM пожаловались, что при работе в системе при выборе записей крутится значок загрузки несколько секунд: При просмотре сетевой активности увидел запуск Rest Service: Действительно, запрос занял 1,62 секунд: Открыв рест сервис, увидел следующий скрипт: output = {}
--todo
output.myTasks, output.errText,output.errNum = SqlQueryRows([[
select
res.button_class,
p.code as bp_process_code,
c.do_title,
count(1) as cnt,
'1' as mass,
json_agg( json_build_object
(
'entity_code', e.code,
'approve_res_id', c.res_id::text,
'pk_uuid',t.entity_pk,
'step_nn',t.step_nn::text,
'nn',t.nn::text,
'approve_t_s_c_id',c.id::text,
'task_id', t.id::text
)) mass_data
from
its_req r
join tasks t on t.entity_pk = r.entity_uuid
join users manager_id on manager_id.id = t.manager_id
join task_statuses status_id on status_id.id=t.status_id
join task_approve_t_s_c c on c.task_approve_t_s_id = approve_t_s_id
join task_approve_res res on res.id=c.res_id
join

Пользователи облачного сервиса документооборота DamuBPM пожаловались, что при работе в системе при выборе записей крутится значок загрузки несколько секунд:

При просмотре сетевой активности увидел запуск Rest Service:

Действительно, запрос занял 1,62 секунд:

-2

Открыв рест сервис, увидел следующий скрипт:

output = {}
--todo

output.myTasks, output.errText,output.errNum = SqlQueryRows([[

select
res.button_class,
p.code as bp_process_code,
c.do_title,
count(1) as cnt,
'1' as mass,
json_agg( json_build_object
(
'entity_code', e.code,
'approve_res_id', c.res_id::text,
'pk_uuid',t.entity_pk,
'step_nn',t.step_nn::text,
'nn',t.nn::text,
'approve_t_s_c_id',c.id::text,
'task_id', t.id::text
)) mass_data
from
its_req r
join tasks t on t.entity_pk = r.entity_uuid
join users manager_id on manager_id.id = t.manager_id
join task_statuses status_id on status_id.id=t.status_id
join task_approve_t_s_c c on c.task_approve_t_s_id = approve_t_s_id
join task_approve_res res on res.id=c.res_id

join bp_processes p on p.id=c.bp_process_id
join entities e on e.id=t.entity_id
left join task_approve_res approve_res_id on approve_res_id.id=t.approve_res_id
left join task_approve_filluser fu on fu.id=t.filluser_id
left join task_types tt on tt.id=t.type_id
where r.id in (select (v->>'id')::bigint from jsonb_array_elements(?) v)

and exists (select 1 from bp_process_vars v where v.process_id=p.id and code='mass')
and
(
t.manager_id in (select ? union select users_id from users_alternate where user_id=? and date1<=now() and date2+interval '1 day'>=now() )
) and
( status_id.code in ('opened','fyi_pending')
)
group by p.code,c.do_title,c.res_id,res.button_class


]],JsonToString(request.input.items), tostring(request.user_id),request.user_id
)

Перенес скрипт в Dbeaver для подробного анализа:

-3

Стоимость плана: 300 000

не изучая стоимость запроса начал вручную убирать куски поздапросов.

Когда убрал кусок с:

select users_id from users_alternate where user_id=1 and date1<=now() and date2+interval '1 day'>=now()

запрос стал работать быстрее:

-4

Проверил индексы по user_id - все имеется:

-5

После длительных экспериментов перенес условие по задачам в join

join tasks t on t.entity_pk = r.entity_uuid
and t.manager_id in (select 1 union select users_id from users_alternate where user_id=1 and date1<=now() and date2+interval '1 day'>=now() )

Ура, стоимость плана уменьшилась до 562