1

Для списка ~ 700 идентификаторов производительность запросов более 20 раз медленнее, чем передача подзапроса, который возвращает эти 700 идентификаторов. Это должно быть наоборот.Оператор Postgresql IN Производительность: список против подзапроса

например. (Первый запрос берет под 400мсом, поздний 9600 мс)

select date_trunc('month', day) as month, sum(total) 
from table_x 
where y_id in (select id from table_y where prop = 'xyz') 
and day between '2015-11-05' and '2016-11-04' 
group by month 

является 20x быстрее на моей машине, чем передача массива напрямую:

select date_trunc('month', day) as month, sum(total) 
from table_x 
where y_id in (1625, 1871, ..., 1640, 1643, 13291, 1458, 13304, 1407, 1765) 
and day between '2015-11-05' and '2016-11-04' 
group by month 

Любой идеи, что может быть проблемой или как оптимизировать и получить такую ​​же производительность?

+0

Насколько велик этот массив? Кроме того, почему первый запрос не написан как простой JOIN? Вы пытались использовать 'EXPLAIN', чтобы проверить, переписывает ли механизм запроса его как JOIN? – Kevin

+0

'где y_id = any (массив [1625, 1871, ..., 1640, 1643, 13291, 1458, 13304, 1407, 1765])' –

ответ

1

Разница простой фильтр против хэша присоединиться:

explain analyze 
select i 
from t 
where i in (500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600); 
               QUERY PLAN                                                       
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
Seq Scan on t (cost=0.00..140675.00 rows=101 width=4) (actual time=0.648..1074.567 rows=101 loops=1) 
    Filter: (i = ANY ('{500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600}'::integer[])) 
    Rows Removed by Filter: 999899 
Planning time: 0.170 ms 
Execution time: 1074.624 ms 

explain analyze 
select i 
from t 
where i in (select i from r); 
                QUERY PLAN              
------------------------------------------------------------------------------------------------------------------- 
Hash Semi Join (cost=3.27..17054.40 rows=101 width=4) (actual time=0.382..240.389 rows=101 loops=1) 
    Hash Cond: (t.i = r.i) 
    -> Seq Scan on t (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.030..117.193 rows=1000000 loops=1) 
    -> Hash (cost=2.01..2.01 rows=101 width=4) (actual time=0.074..0.074 rows=101 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 12kB 
     -> Seq Scan on r (cost=0.00..2.01 rows=101 width=4) (actual time=0.010..0.035 rows=101 loops=1) 
Planning time: 0.245 ms 
Execution time: 240.448 ms 

Чтобы иметь такую ​​же производительность, присоединяемый к массиву:

explain analyze 
select i 
from 
    t 
    inner join 
    unnest(
     array[500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600]::int[] 
    ) u (i) using (i) 
; 
                 QUERY PLAN              
----------------------------------------------------------------------------------------------------------------------- 
Hash Join (cost=2.25..18178.25 rows=100 width=4) (actual time=0.267..243.768 rows=101 loops=1) 
    Hash Cond: (t.i = u.i) 
    -> Seq Scan on t (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.022..118.709 rows=1000000 loops=1) 
    -> Hash (cost=1.00..1.00 rows=100 width=4) (actual time=0.063..0.063 rows=101 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 12kB 
     -> Function Scan on unnest u (cost=0.00..1.00 rows=100 width=4) (actual time=0.028..0.041 rows=101 loops=1) 
Planning time: 0.172 ms 
Execution time: 243.816 ms 

Или используйте синтаксис values:

explain analyze 
select i 
from t 
where i = any (values (500),(501),(502),(503),(504),(505),(506),(507),(508),(509),(510),(511),(512),(513),(514),(515),(516),(517),(518),(519),(520),(521),(522),(523),(524),(525),(526),(527),(528),(529),(530),(531),(532),(533),(534),(535),(536),(537),(538),(539),(540),(541),(542),(543),(544),(545),(546),(547),(548),(549),(550),(551),(552),(553),(554),(555),(556),(557),(558),(559),(560),(561),(562),(563),(564),(565),(566),(567),(568),(569),(570),(571),(572),(573),(574),(575),(576),(577),(578),(579),(580),(581),(582),(583),(584),(585),(586),(587),(588),(589),(590),(591),(592),(593),(594),(595),(596),(597),(598),(599),(600)) 
; 
                 QUERY PLAN              
----------------------------------------------------------------------------------------------------------------------- 
Hash Semi Join (cost=2.53..17053.65 rows=101 width=4) (actual time=0.279..239.888 rows=101 loops=1) 
    Hash Cond: (t.i = "*VALUES*".column1) 
    -> Seq Scan on t (cost=0.00..14425.00 rows=1000000 width=4) (actual time=0.022..117.199 rows=1000000 loops=1) 
    -> Hash (cost=1.26..1.26 rows=101 width=4) (actual time=0.059..0.059 rows=101 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 12kB 
     -> Values Scan on "*VALUES*" (cost=0.00..1.26 rows=101 width=4) (actual time=0.002..0.027 rows=101 loops=1) 
Planning time: 0.242 ms 
Execution time: 239.933 ms 
1

Попробуйте изменить критическую линию к этому:

where y_id = any (values (1625, 1871, ..., 1640, 1643, 13291, 1458, 13304, 1407, 1765)) 
Смежные вопросы