2015-12-10 4 views
0

У меня есть запрос в функции plpgsql (см. Ниже, упрощен для ясности), который замедляет работу после 4 или 5 запусков в 5 раз (время работы от ~ 700 мс до ~ 3,5 секунд). Если я удалю и заново создаю функцию, она начнется быстрее: примерно 5 раз, а затем медленно. Итак, похоже, что что-то происходит с оптимизатором запросов, но я не могу получить план запроса, так как он находится в функции. Если я запустил запрос вне функции с одинаковыми входами, он работает нормально, независимо от того, сколько раз он запускается. Если я прокомментирую 3 левых соединения, удерживая их внутри функции, снова он работает нормально. Итак, я пришел к выводу, что это связано с левыми объединениями, но об этом.Запрос postgresql в функции plpgsql замедляется после нескольких запусков

Подробнее о запросе: у него есть статья with as, после возврата data с примерно 5000 строк и 40 строк; затем он подключается к сети 3 раза, чтобы переместить некоторую информацию из строк в столбцы (это уменьшает количество строк до 1000).

create or replace function public.a_function(
-- 5 input parameters here 
) 

    returns table (a text, b integer, ...) -- about 40 output columns 

as $$ 

declare 
... 
begin 

... --logic to prepare two arrays used in query below: array_a and array_b 

    return query 
    with data as (       -- this part of the query returns ~5000 rows and 40 columns 
    select d.* 
    from public.dashboard_data_view d  -- ~10 million rows in this view 
    where d.organization_id = any (array_a) -- array_a: 4 values in int[] 
    and d.element_id = any (array_b)  -- array_b: ~10,000 values in int[] 
    ) 
    select c.*, c.value, d.value, r.value, s.value 
    from (select * from data where data.population = 'C') c -- this reduces rows down to ~1000 
    left join (select * from data where data.population = 'D') d on d.common_id = c.common_id 
    left join (select * from data where data.population = 'R') r on r.common_id = c.common_id 
    left join (select * from data where data.population = 'S') s on s.common_id = c.common_id 
    ; 

end 

$$ language plpgsql stable; 
    ; 

информация Платформа: Postgres 9.3 на Ubuntu LTS 14 перспективе на Вагрант VM с 4 Гб оперативной памяти и 2 процессоров. shared_buffers = 1000 МБ (1/4-е от общего числа) и work_mem = 128 МБ (разработка машины, не так много происходит параллельно).

Итак, что может вызвать замедление или что я могу сделать для дальнейшего расследования?

Обновление: я вставил значение array_b в запрос как буквальные (вместо того, чтобы использовать переменный), она работала хорошо. В представлении около 16K element_id, и фильтрация около ~ 10K из них, кажется, оптимизатор решает использовать последовательное сканирование вместо сканирования индекса через 5 раз. Это мое подозрение, но я не уверен.

ответ

0

С/оптимизатор запросов понравился дословный для array_b лучше, я перешел на динамический SQL, и накормили переменную в виде литерала:

return query 
execute format(
    'with data as ( -- this part of the query returns ~5000 rows and 40 columns 
    select d.* 
    from public.dashboard_data_view d -- ~10 million rows in this view 
    where d.organization_id = any (%L) -- array_a: 4 values in int[] 
    and d.element_id = any (%L)  -- array_b: ~10,000 values in int[] 
    ) 
    select c.*, c.value, d.value, r.value, s.value 
    from (select * from data where data.population = ''C'') c -- this reduces rows down to ~1000 
    left join (select * from data where data.population = ''D'') d on d.common_id = c.common_id 
    left join (select * from data where data.population = ''R'') r on r.common_id = c.common_id 
    left join (select * from data where data.population = ''S'') s on s.common_id = c.common_id 
    ', array_a, array_b); 

Он работал отлично!

Смежные вопросы