2015-07-09 6 views
0

Этот запрос в настоящее время принимают 4 минуты для запуска:SQL-запрос работает очень медленно - postrges

with name1 as (
    select col1 as a1, col2 as a2, sum(FEE) as a3 
    from s1, date 
    where return_date = datesk and year = 2000 
    group by col1, col2 
) 
select c_id 
from name1 ala1, ss, cc 
where ala1.a3 > (
    select avg(a3) * 1.2 from name1 ctr2 
    where ala1.a2 = ctr2.a2 
) 
    and s_sk = ala1.a2 
    and s_state = 'TN' 
    and ala1.a1 = c_sk 
order by c_id 
limit 100; 

Я поставил work_mem=’1000MB’ и enable-nestloop=off

EXPLAIN ANALYZE этого запроса: http://explain.depesz.com/s/DUa

QUERY PLAN 

----------------------------------------------------------------------------------------------------------------------------------------------------- 
-------------------- 
Limit (cost=59141.02..59141.09 rows=28 width=17) (actual time=253707.928..253707.940 rows=100 loops=1) 
    CTE name1 
    -> HashAggregate (cost=11091.33..11108.70 rows=1390 width=14) (actual time=105.223..120.358 rows=50441 loops=1) 
      Group Key: s1.col1, s1.col2 
      -> Hash Join (cost=2322.69..11080.90 rows=1390 width=14) (actual time=10.390..79.897 rows=55820 loops=1) 
       Hash Cond: (s1.return_date = date.datesk) 
       -> Seq Scan on s1 (cost=0.00..7666.14 rows=287514 width=18) (actual time=0.005..33.801 rows=287514 loops=1) 
       -> Hash (cost=2318.11..2318.11 rows=366 width=4) (actual time=10.375..10.375 rows=366 loops=1) 
         Buckets: 1024 Batches: 1 Memory Usage: 13kB 
         -> Seq Scan on date (cost=0.00..2318.11 rows=366 width=4) (actual time=5.224..10.329 rows=366 loops=1) 
          Filter: (year = 2000) 
          Rows Removed by Filter: 72683 
    -> Sort (cost=48032.32..48032.39 rows=28 width=17) (actual time=253707.923..253707.930 rows=100 loops=1) 
     Sort Key: cc.c_id 
     Sort Method: top-N heapsort Memory: 32kB 
     -> Hash Join (cost=43552.37..48031.65 rows=28 width=17) (actual time=253634.511..253696.291 rows=18976 loops=1) 
       Hash Cond: (cc.c_sk = ala1.a1) 
       -> Seq Scan on cc (cost=0.00..3854.00 rows=100000 width=21) (actual time=0.009..18.527 rows=100000 loops=1) 
       -> Hash (cost=43552.02..43552.02 rows=28 width=4) (actual time=253634.420..253634.420 rows=18976 loops=1) 
        Buckets: 1024 Batches: 1 Memory Usage: 668kB 
        -> Hash Join (cost=1.30..43552.02 rows=28 width=4) (actual time=136.819..253624.375 rows=18982 loops=1) 
          Hash Cond: (ala1.a2 = ss.s_sk) 
          -> CTE Scan on name1 ala1 (cost=0.00..43548.70 rows=463 width=8) (actual time=136.756..253610.817 rows=18982 loops=1) 
           Filter: (a3 > (SubPlan 2)) 
           Rows Removed by Filter: 31459 
           SubPlan 2 
            -> Aggregate (cost=31.29..31.31 rows=1 width=32) (actual time=5.025..5.025 rows=1 loops=50441) 
             -> CTE Scan on name1 ctr2 (cost=0.00..31.27 rows=7 width=32) (actual time=0.032..3.860 rows=8241 loops=50441) 
               Filter: (ala1.a2 = a2) 
               Rows Removed by Filter: 42200 
          -> Hash (cost=1.15..1.15 rows=12 width=4) (actual time=0.036..0.036 rows=12 loops=1) 
           Buckets: 1024 Batches: 1 Memory Usage: 1kB 
           -> Seq Scan on ss (cost=0.00..1.15 rows=12 width=4) (actual time=0.025..0.033 rows=12 loops=1) 
             Filter: (s_state = 'TN'::bpchar) 
Planning time: 0.316 ms 
Execution time: 253708.351 ms 
(36 rows) 

С enable_nestloop = on; EXPLAIN ANLYZE результат: http://explain.depesz.com/s/NPo

QUERY PLAN 

----------------------------------------------------------------------------------------------------------------------------------------------------- 
-------------- 
Limit (cost=54916.36..54916.43 rows=28 width=17) (actual time=257869.004..257869.015 rows=100 loops=1) 
    CTE name1 
    -> HashAggregate (cost=11091.33..11108.70 rows=1390 width=14) (actual time=92.354..104.103 rows=50441 loops=1) 
      Group Key: s1.col1, s1.col2 
      -> Hash Join (cost=2322.69..11080.90 rows=1390 width=14) (actual time=9.371..68.156 rows=55820 loops=1) 
       Hash Cond: (s1.return_date = date.datesk) 
       -> Seq Scan on s1 (cost=0.00..7666.14 rows=287514 width=18) (actual time=0.011..25.637 rows=287514 loops=1) 
       -> Hash (cost=2318.11..2318.11 rows=366 width=4) (actual time=9.343..9.343 rows=366 loops=1) 
         Buckets: 1024 Batches: 1 Memory Usage: 13kB 
         -> Seq Scan on date (cost=0.00..2318.11 rows=366 width=4) (actual time=4.796..9.288 rows=366 loops=1) 
          Filter: (year = 2000) 
          Rows Removed by Filter: 72683 
    -> Sort (cost=43807.66..43807.73 rows=28 width=17) (actual time=257868.994..257868.998 rows=100 loops=1) 
     Sort Key: cc.c_id 
     Sort Method: top-N heapsort Memory: 32kB 
     -> Nested Loop (cost=0.29..43806.98 rows=28 width=17) (actual time=120.358..257845.941 rows=18976 loops=1) 
       -> Nested Loop (cost=0.00..43633.22 rows=28 width=4) (actual time=120.331..257692.654 rows=18982 loops=1) 
        Join Filter: (ala1.a2 = ss.s_sk) 
        Rows Removed by Join Filter: 208802 
        -> CTE Scan on name1 ala1 (cost=0.00..43548.70 rows=463 width=8) (actual time=120.316..257652.636 rows=18982 loops=1) 
          Filter: (a3 > (SubPlan 2)) 
          Rows Removed by Filter: 31459 
          SubPlan 2 
          -> Aggregate (cost=31.29..31.31 rows=1 width=32) (actual time=5.105..5.105 rows=1 loops=50441) 
            -> CTE Scan on name1 ctr2 (cost=0.00..31.27 rows=7 width=32) (actual time=0.032..3.952 rows=8241 loops=50441) 
             Filter: (ala1.a2 = a2) 
             Rows Removed by Filter: 42200 
        -> Materialize (cost=0.00..1.21 rows=12 width=4) (actual time=0.000..0.001 rows=12 loops=18982) 
          -> Seq Scan on ss (cost=0.00..1.15 rows=12 width=4) (actual time=0.007..0.012 rows=12 loops=1) 
           Filter: (s_state = 'TN'::bpchar) 
       -> Index Scan using cc_pkey on cc (cost=0.29..6.20 rows=1 width=21) (actual time=0.007..0.007 rows=1 loops=18982) 
        Index Cond: (c_sk = ala1.a1) 
Planning time: 0.453 ms 
Execution time: 257869.554 ms 
(34 rows) 

Многие другие запросы быстро запустить с enable_nestloop = выкл, нет большой разницы для этого запроса. Сырые данные не очень большие, поэтому 4 минуты - это слишком много. Я ожидал около 4-5 секунд.

Почему так долго? Я пробовал это в обеих версиях постресурсов 9.4 и 9.5. Это то же самое. Может быть, я могу создать индексы бриндов. Но я не уверен, для каких столбцов создавать.

настройка конфигурации:

effective_cache_size   | 89GB 
shared_buffers    | 18GB 
work_mem      | 1000MB 
maintenance_work_mem   | 500MB 
checkpoint_segments   | 32 
constraint_exclusion   | on 
checkpoint_completion_target | 0.5 
+1

Возможно, вы могли бы объяснить, что делает запрос, и предоставить образец daa и желаемые результаты. Могут быть лучшие способы написать логику. –

+1

вы также можете прикрепить все столбцы к таблицам так, чтобы мы знали, где 's_sk' и' s_state' пришли от – cha

+0

. В вашем плане запроса указано, что коррелированный подзапрос в предложении 'WHERE' очень дорог. Это не должно удивлять, поскольку коррелированные подзапросы печально известны тем, что вызывают проблемы с производительностью. Кажется, что вам требуется полное сканирование таблицы CTE каждый раз, когда оно оценивается. –

ответ

3

Как Джон Боллинджер отметил, ваш подзапрос получает оценку для каждой строки основного запроса. Но так как вы в среднем на простой колонке, вы можете легко переместить подзапрос к КТР и вычислить среднее значение один раз, что должно ускорить процесс, чрезвычайно:

with name1 as (
    select col1 as a1, col2 as a2, sum(FEE) as a3 
    from s1, date 
    where return_date = datesk and year = 2000 
    group by col1, col2 
), avg_a3_by_a2 as (
    select a2, avg(a3) * 1.2 as avg12 
    from name1 
    group by a2 
) 
select c_id 
from name1, avg_a3_by_a2, ss, cc 
where name1.a3 > avg_a3_by_a2.avg12 
    and name1.a2 = avg_a3_by_a2.a2 
    and s_sk = name1.a2 
    and s_state = 'TN' 
    and name1.a1 = c_sk 
order by c_id 
limit 100; 

Новый КТР вычисляет среднее + 20 % для каждого отдельного значения a2.

Просьба также использовать синтаксис JOIN вместо разделенных запятыми FROM элементов, поскольку он делает ваш код более читаемым. И если вы начинаете использовать псевдонимы в своем запросе, используйте их последовательно во всех таблицах и столбцах. Я не мог исправить ни один из этих двух вопросов из-за отсутствия информации.