HashAggregate表现缓慢

时间:2017-11-20 10:51:54

标签: postgresql

我有一张桌子喜欢这个:
enter image description here

我的索引是id_station_date_hour

我的疑问:

select id_station,area_type,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_time,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_time_prev,
sum(case when goinside = 1 and(zone1+zone2+zone3+cashiertime+special) > 0 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 180 and (zone1+zone2+zone3+cashiertime+special) < 360 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_3to6,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 180 and (zone1+zone2+zone3+cashiertime+special) < 360 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_3to6_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 360 and (zone1+zone2+zone3+cashiertime+special) < 600 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_6to10,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 360 and (zone1+zone2+zone3+cashiertime+special) < 600 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_6to10_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_less3,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_less3_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 60 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_1to3,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 60 and (zone1+zone2+zone3+cashiertime+special) < 180 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_1to3_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and (zone1+zone2+zone3+cashiertime+special) < 900 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_10to15,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and (zone1+zone2+zone3+cashiertime+special) < 900 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_10to15_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 60 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_less1,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) < 60 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_less1_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 900 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_over15,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 900 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_over15_prev,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then zone1+zone2+zone3+cashiertime+special else 0 end) as ex_z1z2z3z4z5_num_over10,
sum(case when goinside = 1 and (zone1+zone2+zone3+cashiertime+special) >= 600 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as ex_z1z2z3z4z5_num_over10_prev,
sum(case when goinside = 1 and type = 1 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as man,
sum(case when goinside = 1 and type = 2 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as woman,
sum(case when goinside = 1 and type = 3 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as couple,
sum(case when goinside = 1 and type = 4 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as boy,
sum(case when goinside = 1 and type = 5 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as girl,
sum(case when goinside = 1 and type = 6 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as young_couple,
sum(case when goinside = 1 and type = 7 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_man,
sum(case when goinside = 1 and type = 8 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_woman,
sum(case when goinside = 1 and type = 9 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as old_couple,
sum(case when goinside = 1 and type = 10 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as family,
sum(case when goinside = 1 and type = 10 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then family_total else 0 end) as family_total,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as group,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then group_man else 0 end) as group_man,
sum(case when goinside = 1 and type = 11 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then group_woman else 0 end) as group_woman,
sum(case when goinside = 1 and type = 12 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as empty,
sum(case when goinside = 1 and date >= '2017-10-01' and date <= '2017-10-31' and hour >= 9 and hour < 22 then 1 else 0 end) as total_entries,
sum(case when goinside = 1 and type = 1 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as man_prev,
sum(case when goinside = 1 and type = 2 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as woman_prev,
sum(case when goinside = 1 and type = 3 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as couple_prev,
sum(case when goinside = 1 and type = 4 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as boy_prev,
sum(case when goinside = 1 and type = 5 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as girl_prev,
sum(case when goinside = 1 and type = 6 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as young_couple_prev,
sum(case when goinside = 1 and type = 7 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_man_prev,
sum(case when goinside = 1 and type = 8 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_woman_prev,
sum(case when goinside = 1 and type = 9 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as old_couple_prev,
sum(case when goinside = 1 and type = 10 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as family_prev,
sum(case when goinside = 1 and type = 10 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then family_total else 0 end) as family_total_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as grou_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then group_man else 0 end) as group_man_prev,
sum(case when goinside = 1 and type = 11 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then group_woman else 0 end) as group_woman_prev,
sum(case when goinside = 1 and type = 12 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as empty_prev,
sum(case when goinside = 1 and date >= '2017-08-31' and date <= '2017-09-30' and hour >= 9 and hour < 22 then 1 else 0 end) as total_entries_prev 
from data_1034_detail where id_station IN (2399,2397) AND ((date >= '2017-10-01' and date <= '2017-10-31' AND hour >= 9 and hour < 22) OR (date >= '2017-08-31' and date <= '2017-09-30' AND hour >= 9 and hour < 22)) group by id_station, area_type

实际上所有字段都选择区域不同的条件,因此如果我添加更多条件和选定字段,它将使查询速度慢慢运行。在这种情况下如何设置正确的索引?

解释:

'HashAggregate  (cost=304337.96..304338.36 rows=40 width=428) (actual time=7233.402..7233.449 rows=37 loops=1)'
'  Group Key: id_station, area_type'
'  ->  Seq Scan on data_1034_detail  (cost=0.00..17573.72 rows=218904 width=64) (actual time=0.035..394.334 rows=282899 loops=1)'
'        Filter: ((id_station = ANY ('{2399,2397}'::bigint[])) AND (hour >= 9) AND (hour < 22) AND (((date >= '2017-10-01'::date) AND (date <= '2017-10-31'::date)) OR ((date >= '2017-08-31'::date) AND (date <= '2017-09-30'::date))))'
'Planning time: 0.735 ms'
'Execution time: 7234.169 ms'

是否有机会在1s内执行此查询?

1 个答案:

答案 0 :(得分:0)

这是使查询变慢的算法。

我不确定,但如果你使用FILTER子句加总,也许你可以赢得一些。

而不是

sum(CASE WHEN goinside = 1
              AND (zone1 + zone2 + zone3 + cashiertime + special) > 0
              AND date >= '2017-10-01'
              AND date <= '2017-10-31'
              AND hour >= 9
              AND hour < 22
         THEN zone1 + zone2 + zone3 + cashiertime + special
         ELSE 0
    END) AS ex_z1z2z3z4z5_time
你可以写:

sum(zone1 + zone2 + zone3 + cashiertime + special)
   FILTER (WHERE goinside = 1
             AND (zone1 + zone2 + zone3 + cashiertime + special) > 0
             AND date >= '2017-10-01'
             AND date <= '2017-10-31'
             AND hour >= 9
             AND hour < 22) AS ex_z1z2z3z4z5_time

您仍然需要进行所有计算,但总和将会减少。

也许PG-Strom可以帮到你 - 这个扩展委托可以并行化到GPU的操作。