如何改进Postgresql慢查询

时间:2016-09-05 11:51:45

标签: performance postgresql casting union

我使用Postgresql,这是我的表:

CREATE TABLE tbl_cdr
(
  uid serial NOT NULL,
  start_time timestamp without time zone NOT NULL,
  end_time timestamp without time zone NOT NULL,
  error_code smallint NOT NULL DEFAULT 200,
  src_ip character varying(20),
  src_port smallint,
  dest_ip character varying(20),
  dest_port smallint,
  CONSTRAINT tbl_cdr_pkey PRIMARY KEY (uid)
)
WITH (
  OIDS=FALSE
);

CREATE INDEX idx_tbl_cdr_date
  ON tbl_cdr
  USING btree
  ((start_time::date));

CREATE INDEX idx_tbl_cdr_end_time
  ON tbl_cdr
  USING btree
  (end_time);

CREATE INDEX idx_tbl_cdr_start_time
  ON tbl_cdr
  USING btree
  (start_time);

我有一个查询(postgresql),如:

(
select * 
from tbl_cdr  
where cast(start_time as date) in  
(
    select cast(start_time as date) as times 
    from tbl_cdr    
    where ( cast(start_time as date) >= '2016-04-30 22:00:00' and cast(start_time as date)  <= '2016-09-30 20:00:00' ) 
    and ( extract(hour from start_time) >= 22  and extract(hour from start_time) <= 24)      
    group by times  order by times  limit 5 
)   
and ( cast(start_time as date)  >= '2016-04-30 22:00:00'  and cast(start_time as date) <= '2016-09-30 20:00:00' )  
and ( extract(hour from start_time) >= 22  and extract(hour from start_time) <= 24)      
)  
UNION 
(
select *  
from tbl_cdr  
where cast(start_time as date) in  
(
    select cast(start_time as date) as times 
    from tbl_cdr    
    where ( cast(start_time as date) >= '2016-05-01 22:00:00' and cast(start_time as date)  <= '2016-09-30 20:00:00' ) 
    and ( extract(hour from start_time) >= 0  and extract(hour from start_time) < 20)      
    group by times  order by times  limit 5 
)   
and ( cast(start_time as date)  >= '2016-05-01 22:00:00'  and cast(start_time as date) <= '2016-09-30 20:00:00' )  
and ( extract(hour from start_time) >= 0  and extract(hour from start_time) < 20)      
) 
order by start_time asc 

但是效果很慢。

您对性能改进有什么建议吗?

我尝试了以下索引:

CREATE INDEX idx_tbl_cdr_date_casted ON tbl_cdr ( cast(start_time as date) );

CREATE INDEX idx_tbl_cdr_hour_casted ON tbl_cdr ( extract(hour from start_time) );

但这些没有帮助:)

编辑: 查询说明: enter image description here

这是分析输出:

"Sort  (cost=311262.22..311333.53 rows=28524 width=179)"
"  Sort Key: tbl_cdr.start_time"
"  ->  Unique  (cost=305045.14..306613.96 rows=28524 width=179)"
"        ->  Sort  (cost=305045.14..305116.45 rows=28524 width=179)"
"              Sort Key: tbl_cdr.uid, tbl_cdr.start_time, tbl_cdr.end_time, (...)"
"              ->  Append  (cost=75581.47..300396.88 rows=28524 width=179)"
"                    ->  Hash Semi Join  (cost=75581.47..150055.82 rows=14262 width=179)"
"                          Hash Cond: ((tbl_cdr.start_time)::date = ((tbl_cdr_1.start_time)::date))"
"                          ->  Bitmap Heap Scan on tbl_cdr  (cost=608.80..74830.00 rows=28523 width=179)"
"                                Recheck Cond: ((date_part('hour'::text, start_time) >= 22::double precision) AND (date_part('hour'::text, start_time) <= 24::double precision))"
"                                Filter: (((start_time)::date >= '2016-04-30'::date) AND ((start_time)::date <= '2016-09-30'::date))"
"                                ->  Bitmap Index Scan on idx_tbl_cdr_hour_casted  (cost=0.00..601.67 rows=28523 width=0)"
"                                      Index Cond: ((date_part('hour'::text, start_time) >= 22::double precision) AND (date_part('hour'::text, start_time) <= 24::double precision))"
"                          ->  Hash  (cost=74972.66..74972.66 rows=1 width=4)"
"                                ->  Limit  (cost=74972.64..74972.65 rows=1 width=8)"
"                                      ->  Sort  (cost=74972.64..74972.65 rows=1 width=8)"
"                                            Sort Key: ((tbl_cdr_1.start_time)::date)"
"                                            ->  HashAggregate  (cost=74972.62..74972.63 rows=1 width=8)"
"                                                  Group Key: (tbl_cdr_1.start_time)::date"
"                                                  ->  Bitmap Heap Scan on tbl_cdr tbl_cdr_1  (cost=608.80..74901.31 rows=28523 width=8)"
"                                                        Recheck Cond: ((date_part('hour'::text, start_time) >= 22::double precision) AND (date_part('hour'::text, start_time) <= 24::double precision))"
"                                                        Filter: (((start_time)::date >= '2016-04-30'::date) AND ((start_time)::date <= '2016-09-30'::date))"
"                                                        ->  Bitmap Index Scan on idx_tbl_cdr_hour_casted  (cost=0.00..601.67 rows=28523 width=0)"
"                                                              Index Cond: ((date_part('hour'::text, start_time) >= 22::double precision) AND (date_part('hour'::text, start_time) <= 24::double precision))"
"                    ->  Hash Semi Join  (cost=75581.47..150055.82 rows=14262 width=179)"
"                          Hash Cond: ((tbl_cdr_2.start_time)::date = ((tbl_cdr_3.start_time)::date))"
"                          ->  Bitmap Heap Scan on tbl_cdr tbl_cdr_2  (cost=608.80..74830.00 rows=28523 width=179)"
"                                Recheck Cond: ((date_part('hour'::text, start_time) >= 0::double precision) AND (date_part('hour'::text, start_time) < 20::double precision))"
"                                Filter: (((start_time)::date >= '2016-05-01'::date) AND ((start_time)::date <= '2016-09-30'::date))"
"                                ->  Bitmap Index Scan on idx_tbl_cdr_hour_casted  (cost=0.00..601.67 rows=28523 width=0)"
"                                      Index Cond: ((date_part('hour'::text, start_time) >= 0::double precision) AND (date_part('hour'::text, start_time) < 20::double precision))"
"                          ->  Hash  (cost=74972.66..74972.66 rows=1 width=4)"
"                                ->  Limit  (cost=74972.64..74972.65 rows=1 width=8)"
"                                      ->  Sort  (cost=74972.64..74972.65 rows=1 width=8)"
"                                            Sort Key: ((tbl_cdr_3.start_time)::date)"
"                                            ->  HashAggregate  (cost=74972.62..74972.63 rows=1 width=8)"
"                                                  Group Key: (tbl_cdr_3.start_time)::date"
"                                                  ->  Bitmap Heap Scan on tbl_cdr tbl_cdr_3  (cost=608.80..74901.31 rows=28523 width=8)"
"                                                        Recheck Cond: ((date_part('hour'::text, start_time) >= 0::double precision) AND (date_part('hour'::text, start_time) < 20::double precision))"
"                                                        Filter: (((start_time)::date >= '2016-05-01'::date) AND ((start_time)::date <= '2016-09-30'::date))"
"                                                        ->  Bitmap Index Scan on idx_tbl_cdr_hour_casted  (cost=0.00..601.67 rows=28523 width=0)"
"                                                              Index Cond: ((date_part('hour'::text, start_time) >= 0::double precision) AND (date_part('hour'::text, start_time) < 20::double precision))"

0 个答案:

没有答案