我正在尝试加速postgresql中的一些查询,目前我觉得很慢,考虑到我想按日期范围,目前我有这个:
select enc.inputdatetime::date dateMed, enc.transmissioncode,
max(det.devicelevel) devicelevel, max(det.pressure) pressure,
max(det.battery) battery,enc.remotelocationid,max(det.loop1con) loop1con
from tl.tlinputdetail det
inner join tl.tlinputtable enc on det.oldmedicionid = enc.oldmedicionid
where TRIM(enc.transmissioncode)= '005'
and enc.inputdatetime::date between '2015-12-12' and '2016-11-12'
group by
enc.transmissioncode,enc.remotelocationid,enc.inputdatetime::date
order by
enc.inputdatetime::date asc;
总查询运行时间:47.6秒检索到60行。
如何增加查询?我在两个表中都有索引,包括oldmedicionid列,传输码和inputdatetime
查询说明
"Sort (cost=105519.94..105519.96 rows=7 width=30)"
" Sort Key: ((enc.inputdatetime)::date)"
" -> HashAggregate (cost=105519.76..105519.85 rows=7 width=30)"
" Group Key: (enc.inputdatetime)::date, enc.transmissioncode, enc.remotelocationid"
" -> Nested Loop (cost=0.43..105517.50 rows=129 width=30)"
" -> Seq Scan on tlinputtable enc (cost=0.00..104881.30 rows=64 width=31)"
" Filter: (((inputdatetime)::date >= '2015-12-12'::date) AND ((inputdatetime)::date <= '2016-11-12'::date) AND (btrim((transmissioncode)::text) = '005'::text))"
" -> Index Scan using tlinputdetail_oldmedicionididx on tlinputdetail det (cost=0.43..9.90 rows=4 width=15)"
" Index Cond: (oldmedicionid = enc.oldmedicionid)"
详细解释,分析,详细
"Sort (cost=105519.94..105519.96 rows=7 width=30) (actual time=57948.774..57948.782 rows=61 loops=1)"
" Output: ((enc.inputdatetime)::date), enc.transmissioncode, (max((det.devicelevel)::text)), (max((det.pressure)::text)), (max((det.battery)::text)), enc.remotelocationid, (max((det.loop1con)::text))"
" Sort Key: ((enc.inputdatetime)::date)"
" Sort Method: quicksort Memory: 29kB"
" -> HashAggregate (cost=105519.76..105519.85 rows=7 width=30) (actual time=57948.655..57948.717 rows=61 loops=1)"
" Output: ((enc.inputdatetime)::date), enc.transmissioncode, max((det.devicelevel)::text), max((det.pressure)::text), max((det.battery)::text), enc.remotelocationid, max((det.loop1con)::text)"
" Group Key: (enc.inputdatetime)::date, enc.transmissioncode, enc.remotelocationid"
" -> Nested Loop (cost=0.43..105517.50 rows=129 width=30) (actual time=21.621..57708.114 rows=62181 loops=1)"
" Output: (enc.inputdatetime)::date, enc.transmissioncode, enc.remotelocationid, det.devicelevel, det.pressure, det.battery, det.loop1con"
" -> Seq Scan on tl.tlinputtable enc (cost=0.00..104881.30 rows=64 width=31) (actual time=0.143..1641.444 rows=20727 loops=1)"
" Output: enc.inputid, enc.inputdatetime, enc.packagesqty, enc.remotelocationid, enc.transmissioncode, enc.oldmedicionid"
" Filter: (((enc.inputdatetime)::date >= '2015-12-12'::date) AND ((enc.inputdatetime)::date <= '2016-11-12'::date) AND (btrim((enc.transmissioncode)::text) = '005'::text))"
" Rows Removed by Filter: 2556266"
" -> Index Scan using tlinputdetail_oldmedicionididx on tl.tlinputdetail det (cost=0.43..9.90 rows=4 width=15) (actual time=2.467..2.699 rows=3 loops=20727)"
" Output: det.inputdetailid, det.inputid, det.devicelevel, det.pressure, det.battery, det.inputdatetime, det.devicecontrol, det.volumecon, det.pressurevolumecon, det.weightcon, det.decimalunit, det.weightunitcon, det.loop1con, det.loop2co (...)"
" Index Cond: (det.oldmedicionid = enc.oldmedicionid)"
"Planning time: 0.549 ms"
"Execution time: 57948.902 ms"
答案 0 :(得分:2)
从解释中可以看出,tlinputdetail是一个设备表,tlinputtable是一个包含实际主数据的表。解释显示只有使用的索引是在tlinputdetail上,而查询速度慢的原因是没有过滤条件确实使用任何类型的索引,数据库被迫在tlinputtable上使用序列扫描,我认为这是一个非常大的表。要优化此查询,您应该创建2个索引: 在inputdatetime上
CREATE INDEX ON tl.tlinputtable ((inputdatetime::date) ASC NULLS LAST);
和传输码
CREATE INDEX ON tl.tlinputtable ((trim(transmissioncode)) ASC NULLS LAST);
编辑:
表示时区为时区,为
CREATE INDEX ON tl.tlinputtable (DATE(inputdatetime AT TIME ZONE 'UTC') ASC NULLS LAST);
并使用类似这样的东西
(date(timezone('UTC'::text, inputdatetime )) between '2015-01-01'::date and ....)
使用您需要的时区而不是UTC
可能会有所帮助link