SQL语句优化,使用postgresql数据库,查询下面sql,需要20多分钟:

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL语句优化,使用postgresql数据库,查询下面sql,需要20多分钟:相关的知识,希望对你有一定的参考价值。

select
sum(case when d.acpt_ind='1' and (b.SYSTEM_CD is null or b.SYSTEM_CD='A') and (d.cuss_ind=1 or d.WebCKI_ind=1) and m.flt_seg_day_id is not null then 1
when c.SYSTEM_CD is not null and d.acpt_ind='1' and a.airln_cd in ('MF','CZ','OQ') and d.cuss_ind=0 and d.WebCKI_ind=0 and c.cki_typ in ('C','W') and m.flt_seg_day_id is not null then 1
else 0 end) as airpt_sec_bc,
sum(case when d.acpt_ind='1' and (b.SYSTEM_CD is null or b.SYSTEM_CD='A') and (d.cuss_ind=1 or d.WebCKI_ind=1) and m.flt_seg_day_id is not null then 1
when c.SYSTEM_CD is not null and d.acpt_ind='1' and a.airln_cd in ('MF','CZ','OQ') and d.cuss_ind=0 and d.WebCKI_ind=0 and c.cki_typ in ('C','W') and m.flt_seg_day_id is not null then 1
else 0 end) as airpt_sec_bag
from dss_pbidt.dcs_flt a
inner join
(select flt_seg_day_id,pax_hist_id,acpt_ind,chkin_pid_nbr,cuss_ind,webcki_ind from dss_pdata.enr_check_in_event
union all
select flt_seg_day_id,pax_hist_id,acpt_ind,chkin_pid_nbr,cuss_ind,webcki_ind from dss_phist.enr_check_in_event_h2015
union all
select flt_seg_day_id,pax_hist_id,acpt_ind,chkin_pid_nbr,cuss_ind,webcki_ind from dss_phist.enr_check_in_event_h2014)d
on( a.flt_seg_day_id=d.flt_seg_day_id
and
d.acpt_ind=1
)
left outer join (select distinct trim(both from PID_NBR) as PID_NBR,SYSTEM_CD from dss_pdata.PRT_CUSS_PID where cz_ind=0)b
on (trim(both from d.chkin_pid_nbr) = b.PID_NBR)
left outer join (select distinct trim(both from PID_NBR) as PID_NBR,SYSTEM_CD,cki_typ from dss_pdata.PRT_CUSS_PID where cz_ind=1)c
on (trim(both from d.chkin_pid_nbr) = c.PID_NBR)
left outer join
(select distinct s.flt_seg_day_id as flt_seg_day_id,s.pax_hist_id as pax_hist_id from
(select opr_dt,flt_seg_day_id,pax_hist_id,hist_actn_cd,opr_pid_nbr from dss_pdata.enr_pax_cki_history
union all
select opr_dt,flt_seg_day_id,pax_hist_id,hist_actn_cd,opr_pid_nbr from dss_phist.enr_pax_cki_history_h2015
union all
select opr_dt,flt_seg_day_id,pax_hist_id,hist_actn_cd,opr_pid_nbr from dss_phist.enr_pax_cki_history_h2014 ) s
where s.opr_dt>='2015-01-01' and s.opr_dt<'2015-02-01' and ((s.hist_actn_cd='BC' and s.opr_pid_nbr in (select distinct(pid_nbr) from
dss_pdata.prt_cuss_pid where system_cd in ('P','H') and cz_ind='0' )) or s.hist_actn_cd='BAG')
)m
on
(
d.flt_seg_day_id=m.flt_seg_day_id
and
d.pax_hist_id=m.pax_hist_id
)
where a.lcl_dep_date between '20150101' and '20150201'

参考技术A postgresql(8.2)的配置文件中有一个参数log_min_duration_statement,意思是只log执行时间大于设定值的语句,如果设为0,表示log所有语句;如果设为-1,表示不log任何语句。
看起来,这个配置选项对性能的调整是很有用的,比如可以设置:
log_min_duration_statement = 1000
则只log执行时间大于1s的语句,重点优化这些sql语句就好了。
然而,奇怪的,这个选项不太容易生效!经过反复试验,原来需要如下配置:
#debug_print_parse = off
#debug_print_rewritten = off
#debug_print_plan = off
#debug_pretty_print = off
log_connections = off
#log_disconnections = off
log_duration = off
log_line_prefix = '%t [%p]: [%l-1] ' # Special values:
# %u = user name
# %d = database name
# %r = remote host and port
# %h = remote host
# %p = PID
# %t = timestamp (no milliseconds)
# %m = timestamp with milliseconds
# %i = command tag
# %c = session id
# %l = session line number
# %s = session start timestamp
# %x = transaction id
# %q = stop here in non-session
# processes
# %% = '%'
# e.g. '<%u%%%d> '
log_statement = 'none' # none, mod, ddl, all
#log_statement = 'all' # none, mod, ddl, all
#log_hostname = off
注意看上面的其中两个选项的设置:
log_duration = off
log_statement = 'none'
这两个选项的意思是不log任何sql语句和执行时间,但是恰恰是关闭了这两个,log_min_duration_statement才会生效!可能postgresql内部 对这两个选项做了“互斥”处理吧。本回答被提问者采纳

如何在PostgreSQL中使用partial index来优化SQL?

一 案例背景

从生产控制台上看到一条下述SQL:


格式化之后SQL语句为:

select '01' status, count(1) from t_ai_prd_item where status = '01' and deleted = false

union all 

select '02' status, count(1) from t_ai_prd_item where status = '02' and deleted = false


一个union all的联合查询,每次执行耗时1秒。有没有优化余地呢?


二 优化分析

1 查看原表数据量分布:

ai=> select count(*) from t_ai_prd_item;                       

  count  

---------

 1395189

(1 row)

ai=> select count(*),status from t_ai_prd_item group by status;

  count  | status 

---------+--------

         364 | 04

           25 | 05

       2835 | 02

 1391965 | 06

(4 rows)

ai=> 


分析发现,表1中有1395189条记录,status='01'的记录为0,status='02'的记录为2835条。


2 那么在status字段上建立一个btree index,效果会怎么样呢?

如何在PostgreSQL中使用partial index来优化SQL?

效果不错,但是结合到实际业务场景,此处只是针对status='01'和status='02'的情况来做统计。那么有没有更好的方法来解决这个场景呢?


3 创建1个partial index来测试 

如何在PostgreSQL中使用partial index来优化SQL?

对比,发现SQL的执行效率几乎没有差别。但是:


4 小结:

在确保SQL执行效率的同时,这个partial index所占的存储空间是b-tree index的1/384,大大降低了存储空间的开销。


三 关于partial index

1 什么是partial index?

分区索引是基于表中部分数据建立的,被索引的部分数据是原数据的一个子集。这个子集数据是基于某些条件可以明确计算出来的。


2 partial index适用场景?

对于表中数据分布“不均匀”的场景,比如某些数据占据绝大多数,而其它一些数据只占少量,且要满足查询条件针是对那些小数据量的查询情形。此例正好满足这种情况,总数据量为140万左右,而状态为01和02的数据只占极少的比例,且查询是针对状态为01和02的查询。

 

通过partial index可以排除大量普通数据或业务上“不感兴趣”的数据。如:一个在线订单系统,可以针对那些不在经常访问的客户端IP范围之外的IP进行创建分区索引,或者针对已下单还未支付的订单进行分区索引的创建。这样,当查询那些不在常用IP范围内的订单,或者那些已下单未支付的订单信息时,可以保证查询效率。

 

3 partial index的优势?

由于其是针对部分数据进行索引,显然同传统b-tree索引相比,其所占磁盘空间将大大缩小。当重建维护这些分区索引时,速度也非常快。

 

4 参考

https://www.postgresql.org/docs/9.3/static/indexes-partial.html




以上是关于SQL语句优化,使用postgresql数据库,查询下面sql,需要20多分钟:的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL之慢SQL语句

PostgreSQL之慢SQL语句

Sql优化 PostgreSQL存储过程

SQL语句常见优化十大案例

如何在PostgreSQL中使用partial index来优化SQL?

数据库占用大量内存的检测和优化(PostgreSQL)