对于庞大的数据,检索sql的编写要格外小心,有很多平时不注意的sql可能就会变成瓶颈。
比如, 我们有个系统, 其中t96_pd_log表,记录数8000w多,在开发阶段乃至用了那么多年都没问题, 最近却发生频繁死锁的问题, 查数据库后台发现问题出在一个select语句上, 它耗时高达2.4-2.7s,这对于一个需要高并发的系统来说当然是致命的。
数据表t96_pd_log有两条index, 一条的字段组成是f96_mgtbarcd,另一条的字段组成是f96_result_type, 检索sql是这样写的:
select recseq,f96_create_dt,f96_op from t96_pd_log where f96_mgtbarcd='113D1907032385'
and f96_station='AS01-L113' and f96_result_type='TFT'
and f96_qty=1 order by f96_create_dt desc limit 1
意在找出AS01-L113站位最近一条有效的记录,而这条sql有足够的index支持,但耗时高达2.7s。
F7查一下,居然包含f96_result_type的这支索引也参与运算, 这就出事了, 因为f96_result_type有相同值的记录极其多,从图3也可以看出, 这也是主要耗费时间的环节。
通过数据分析, f96_mgtbarcd值相同的记录数很少, 所以我们可以将顺序改一下,先用f96_mgtbarcd作为过滤器生成一个子集后, 再从这个子集里面做f96_result_type等过滤, 跑了一下,13ms, 足足快了这样就快200多倍,如下:
with a as (
select recseq,f96_create_dt,f96_op,f96_station,f96_result_type,f96_qty from t96_pd_log where f96_mgtbarcd='113D1907032385'
)
select recseq,f96_create_dt,f96_op from a where f96_station='AS01-L113' and f96_result_type='TP' and f96_qty=1 order by f96_create_dt desc limit 1
ps:我用的工具是 pgAdmin自带的,F7, Shift-F7
补充:PostgreSql查询优化之根据执行计划优化SQL
1、执行计划路径选择
postgresql查询规划过程中,查询请求的不同执行方案是通过建立不同的路径来表达的,在生成许多符合条件的路径之后,要从中选择出代价最小的路径(基于成本运算),把它转化为一个计划,传递给执行器执行,规划器的核心工作就是生成多条路径,然后从中找出最优的那一条。
1.1代价评估
评估路径优劣的依据是用系统表pg_statistic中的统计信息估算出来的不同路径的代价(cost),PostgreSQL估计计划成本的方式:基于统计信息估计计划中各个节点的成本。PostgreSQL会分析各个表来获取一个统计信息样本(这个操作通常是由autovacuum这个守护进程周期性的执行analyze,来收集这些统计信息,然后保存到pg_statistic和pg_class里面)。
1.2用于估算代价的参数postgresql.conf