Postgresql的select优化操作(快了200倍)

对于庞大的数据,检索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

# - Planner Cost Constants -
#seq_page_cost = 1.0  # measured on an arbitrary scale 顺序磁盘扫描时单个页面的开销
#random_page_cost = 4.0  # same scale as above 随机磁盘访问时单页面的读取开销
#cpu_tuple_cost = 0.01  # same scale as above cpu处理每一行的开销
#cpu_index_tuple_cost = 0.005 # same scale as above cpu处理每个索引行的开销
#cpu_operator_cost = 0.0025 # same scale as above cpu处理每个运算符或者函数调用的开销
#parallel_tuple_cost = 0.1 # same scale as above 计算并行处理的成本,如果成本高于非并行,则不会开启并行处理。
#parallel_setup_cost = 1000.0 # same scale as above
#min_parallel_relation_size = 8MB
#effective_cache_size = 4GB 再一次索引扫描中可用的文件系统内核缓冲区有效大小

也可以使用 show all的方式查看

1.3 路径的选择

--查看表信息
highgo=# \d t_jcxxgl_tjaj
  Table "db_jcxx.t_jcxxgl_tjaj"

 Column |  Type  | Modifiers --------------+--------------------------------+-----------
 c_bh | character(32)   | not null
 c_xzdm | character varying(300)  |
 c_jgid | character(32)   |
 c_ajbm | character(22)   |
...
Indexes:
 "t_jcxxgl_tjaj_pkey" PRIMARY KEY, btree (c_bh)
 "idx_ttjaj_cah" btree (c_ah)
 "idx_ttjaj_dslrq" btree (d_slrq)

首先更新统计信息vacuum analyze t_jcxxgl_tjaj,许多时候可能因为统计信息的不准确导致了不正常的执行计划--执行计划。

--执行计划,全表扫描
highgo=# explain (analyze,verbose,costs,buffers,timing)select c_bh,c_xzdm,c_jgid,c_ajbm from t_jcxxgl_tjaj where d_slrq >='2018-03-18';
       QUERY PLAN      ------------------------------------------------------------------------------------------------------------
 Seq Scan on db_jcxx.t_jcxxgl_tjaj (cost=0.00..9.76 rows=3 width=96) (actual time=1.031..1.055 rows=3 loops
=1)
 Output: c_bh, c_xzdm, c_jgid, c_ajbm
 Filter: (t_jcxxgl_tjaj.d_slrq >= '2018-03-18'::date)
 Rows Removed by Filter: 138
 Buffers: shared hit=8
 Planning time: 6.579 ms
 Execution time: 1.163 ms
(7 rows)

如上,d_slrq是有索引的,但是执行计划中并没有走索引,为什么呢?我们继续往下看。

--执行计划,关闭全表扫描
highgo=# set session enable_seqscan = off;
SET
highgo=# explain (analyze,verbose,costs,buffers,timing)select c_bh,c_xzdm,c_jgid,c_ajbm from t_jcxxgl_tjaj where d_slrq >='2018-03-18';
        QUERY PLAN        ------------------------------------------------------------------------------------------------------------

 Index Scan using idx_ttjaj_dslrq on db_jcxx.t_jcxxgl_tjaj (cost=0.14..13.90 rows=3 width=96) (actual time=0.012..0.026 rows=3 loops=1)
 Output: c_bh, c_xzdm, c_jgid, c_ajbm
 Index Cond: (t_jcxxgl_tjaj.d_slrq >= '2018-03-18'::date)
 Buffers: shared hit=4
 Planning time: 0.309 ms
 Execution time: 0.063 ms
(6 rows)

d_slrq上面有btree索引,但是查看执行计划并没有走索引,这是为什么呢?

代价计算:

一个路径的估算由三部分组成:启动代价(startup cost),总代价(totalcost),执行结果的排序方式(pathkeys)

代价估算公式:

总代价=启动代价+I/O代价+CPU代价(cost=S+P+W*T)

P:执行时要访问的页面数,反应磁盘的I/O次数

T:表示在执行时所要访问的元组数,反映了cpu开销

W:表示磁盘I/O代价和CPU开销建的权重因子

统计信息:

统计信息的其中一部分是每个表和索引中项的总数,以及每个表和索引占用的磁盘块数。这些信息保存在pg_class表的reltuples和relpages列中。我们可以这样查询相关信息:

--查看统计信息
highgo=# select relpages,reltuples from pg_class where relname ='t_jcxxgl_tjaj';
 relpages | reltuples ----------+-----------
 8 | 141
(1 row)

total_cost = 1(seq_page_cost)*8(磁盘总页数)+0.01(cpu_tuple_cost)*141(表的总记录数)+0.0025(cpu_operation_cost)*141(表的总记录数)=9.7625

可以看到走索引的cost=13.90比全表扫描cost=9.76要大。所以上面没有关闭全表扫描的时候,根据成本代价,执行计划走的全表扫描。在表较小的情况下,全表扫描比索引扫描更有效, index scan 至少要发生两次I/O,一次是读取索引块,一次是读取数据块。

2、一个SQL优化实例

2.1慢SQL:

select c_ajbh, c_ah, c_cbfy, c_cbrxm, d_larq, d_jarq, n_dbjg, c_yqly from db_zxzhld.t_zhld_db dbxx join db_zxzhld.t_zhld_ajdbxx dbaj on dbxx.c_bh = dbaj.c_dbbh where dbxx.n_valid=1 and dbxx.n_state in (1,2,3) and dbxx.c_dbztbh='1003' and dbaj.c_zblx='1003' and dbaj.c_dbfy='0' and dbaj.c_gy = '2550' and c_ajbh in (select distinct c_ajbh from db_zxzhld.t_zhld_zbajxx where n_dbzt = 1 and c_zblx = '1003' and c_gy = '2550' ) order by d_larq asc, c_ajbh asc limit 15 offset 0;

慢sql耗时:7s

先过下这个sql是干什么的、首先dbxx和dbaj的一个join连接然后dbaj.c_ajbh要包含在zbaj表里面,做了个排序,取了15条记录、大概就这样。

Sql有个缺点就是我不知道查询的字段是从那个表里面取的、建议加上表别名.字段。

查看该sql的表的数据量:

t_zhld_db :1311

t_zhld_ajdbxx :341296

t_zhld_zbajxx :1027619

执行计划:

01 Limit (cost=36328.67..36328.68 rows=1 width=107) (actual time=88957.677..88957.729 rows=15 loops=1)

02 -> Sort (cost=36328.67..36328.68 rows=1 width=107) (actual time=88957.653..88957.672 rows=15 loops=1)

03  Sort Key: dbaj.d_larq, dbaj.c_ajbh

04  Sort Method: top-N heapsort Memory: 27kB

05  -> Nested Loop Semi Join (cost=17099.76..36328.66 rows=1 width=107) (actual time=277.794..88932.662 rows=8605 loops=1)

06  Join Filter: ((dbaj.c_ajbh)::text = (t_zhld_zbajxx.c_ajbh)::text)

07  Rows Removed by Join Filter: 37018710

08  -> Nested Loop (cost=0.00..19200.59 rows=1 width=107) (actual time=199.141..601.845 rows=8605 loops=1)

09   Join Filter: (dbxx.c_bh = dbaj.c_dbbh)

10   Rows Removed by Join Filter: 111865

11   -> Seq Scan on t_zhld_ajdbxx dbaj (cost=0.00..19117.70 rows=219 width=140) (actual time=198.871..266.182 rows=8605 loops=1)

12    Filter: ((n_valid = 1) AND ((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))

13    Rows Removed by Filter: 332691

14   -> Materialize (cost=0.00..66.48 rows=5 width=33) (actual time=0.001..0.017 rows=14 loops=8605)

15    -> Seq Scan on t_zhld_db dbxx (cost=0.00..66.45 rows=5 width=33) (actual time=0.044..0.722 rows=14 loops=1)

16     Filter: ((n_valid = 1) AND ((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))

17     Rows Removed by Filter: 1297

18  -> Materialize (cost=17099.76..17117.46 rows=708 width=32) (actual time=0.006..4.890 rows=4303 loops=8605)

19   -> HashAggregate (cost=17099.76..17106.84 rows=708 width=32) (actual time=44.011..54.924 rows=8605 loops=1)

20    Group Key: t_zhld_zbajxx.c_ajbh

21    -> Bitmap Heap Scan on t_zhld_zbajxx (cost=163.36..17097.99 rows=708 width=32) (actual time=5.218..30.278 rows=8605 loops=1)

22     Recheck Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text))

23     Filter: ((c_gy)::text = '2550'::text)

24     Rows Removed by Filter: 21849

25     Heap Blocks: exact=960

26     -> Bitmap Index Scan on i_tzhldzbajxx_zblx_dbzt (cost=0.00..163.19 rows=5876 width=0) (actual time=5.011..5.011 rows=30458 loops=1)

27     Index Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text))

28 Planning time: 1.258 ms
29 Execution time: 88958.029 ms

执行计划解读:

1:第27->21行,通过索引i_tzhldzbajxx_zblx_dbzt过滤表t_zhld_zbajxx的数据,然后根据过滤条件(c_gy)::text = '2550'::text过滤最终返回8605条数据

2:第17->15行,根据条件过滤t_zhld_db表的数据,最终返回了14条数据

3:第20->19行,对表t_zhld_zbajxx做group by的操作

4:第13->11行,全表扫描t_zhld_ajdbxx 最终返回了8605条数据

5:第08行,根据t_zhld_ajdbxx返回的8605条结果集作为驱动表和t_zhld_db的结果集(14条)做嵌套循环,t_zhld_db的结果集被循环了8605次。然后过滤掉了其中的111865条记录,那么最终将得到(8605*14-111865) = 8605

6:第07->05行,根据第08和18行返回的结果集最终做了Nested Loop Semi Join,第18行的4303条结果集被循环了8605次,(4303*8605-37018710)=8605

7: 第04->02行,对最终的8605条记录进行排序

8:第01行,limit最终获取15条记录

整个执行计划中耗时最长的地方在05行Nested Loop Semi Join,actual time=277.794..88932.662, 表db_zxzhld.t_zhld_db dbxx和db_zxzhld.t_zhld_ajdbxx均是全表扫描

2.2具体优化步骤

查看索引页并没有索引,创建c_ajbh,c_dbbh等逻辑外键的索引

drop index if exists I_T_ZHLD_AJDBXX_AJBH;
create index I_T_ZHLD_AJDBXX_AJBH on T_ZHLD_AJDBXX (c_ajbh);
commit;
drop index if exists I_T_ZHLD_AJDBXX_DBBH;
create index I_T_ZHLD_AJDBXX_DBBH on T_ZHLD_AJDBXX (c_dbbh);
commit;

创建d_larq,c_ajbh的排序索引:

drop index if exists I_T_ZHLD_AJDBXX_m6;create index I_T_ZHLD_AJDBXX_m6 on T_ZHLD_AJDBXX (c_zblx,c_dbfy,c_gy,d_larq asc,c_ajbh asc);
commit;
drop index if exists I_T_ZHLD_ZBAJXX_h3 ;
create index I_T_ZHLD_ZBAJXX_h3 on db_zxzhld.t_zhld_zbajxx (n_dbzt,c_zblx,c_gy,c_gy);
commit;

创建索引后执行计划有了改变,原来的dbaj表和dbxx表先做nestedloop变成了zbaj和dbaj表先做了nestedloop join,总的cost也从36328.68降到了12802.87,

执行计划

Limit (cost=12802.87..12802.87 rows=1 width=107) (actual time=4263.598..4263.648 rows=15 loops=1)
 -> Sort (cost=12802.87..12802.87 rows=1 width=107) (actual time=4263.592..4263.609 rows=15 loops=1)
 Sort Key: dbaj.d_larq, dbaj.c_ajbh
 Sort Method: top-N heapsort Memory: 27kB
 -> Nested Loop (cost=2516.05..12802.86 rows=1 width=107) (actual time=74.240..4239.723 rows=8605 loops=1)
  Join Filter: (dbaj.c_dbbh = dbxx.c_bh)
  Rows Removed by Join Filter: 111865
  -> Nested Loop (cost=2516.05..12736.34 rows=1 width=140) (actual time=74.083..327.974 rows=8605 loops=1)
   -> HashAggregate (cost=2515.62..2522.76 rows=714 width=32) (actual time=74.025..90.185 rows=8605 loops=1)
    Group Key: ("ANY_subquery".c_ajbh)::text
    -> Subquery Scan on "ANY_subquery" (cost=2499.56..2513.84 rows=714 width=32) (actual time=28.782..59.823 rows=8605 loops=1)
    -> HashAggregate (cost=2499.56..2506.70 rows=714 width=32) (actual time=28.778..39.968 rows=8605 loops=1)
     Group Key: zbaj.c_ajbh
     -> Index Scan using i_t_zhld_zbajxx_h3 on t_zhld_zbajxx zbaj (cost=0.42..2497.77 rows=715 width=32) (actual time=0.062..15.104 rows=8605 loops=1)
      Index Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text))
   -> Index Scan using i_t_zhld_ajdbxx_ajbh on t_zhld_ajdbxx dbaj (cost=0.42..14.29 rows=1 width=140) (actual time=0.015..0.021 rows=1 loops=8605)
    Index Cond: ((c_ajbh)::text = ("ANY_subquery".c_ajbh)::text)
    Filter: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))
    Rows Removed by Filter: 1
  -> Seq Scan on t_zhld_db dbxx (cost=0.00..66.45 rows=5 width=33) (actual time=0.015..0.430 rows=14 loops=8605)
   Filter: ((n_valid = 1) AND ((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
   Rows Removed by Filter: 1298
Planning time: 1.075 ms
Execution time: 4263.803 ms

执行的时间还是要4s左右仍然不满足需求,并且没有使用上I_T_ZHLD_AJDBXX_m6这个索引。

2.3等价改写SQL(1)

等价改写:将排序条件加入db_zxzhld.t_zhld_ajdbxx让其先排序,再和t_zhld_db表连接。

修改后sql:

Select dbaj.c_ajbh, dbaj.c_ah, dbaj.c_cbfy, dbaj.c_cbrxm, dbaj.d_larq, dbaj.d_jarq, dbaj.n_dbjg, dbaj.c_yqly from (select * from db_zxzhld.t_zhld_db where n_valid=1 and n_state in (1,2,3) and c_dbztbh='1003' )dbxx
 join (select * from db_zxzhld.t_zhld_ajdbxx where n_valid=1 and c_zblx='1003'
 and c_dbfy='0' and c_gy = '2550' and
c_ajbh in (select distinct c_ajbh from db_zxzhld.t_zhld_zbajxx where n_dbzt = 1 and c_zblx = '1003' and c_gy = '2550' ) order by d_larq asc, c_ajbh asc)dbajon dbxx.c_bh = dbaj.c_dbbh
 limit 15 offset 0

再次查看执行计划:

Limit (cost=3223.92..3231.97 rows=1 width=107) (actual time=127.291..127.536 rows=15 loops=1)

 -> Nested Loop (cost=3223.92..3231.97 rows=1 width=107) (actual time=127.285..127.496 rows=15 loops=1)

 -> Sort (cost=3223.64..3223.65 rows=1 width=140) (actual time=127.210..127.225 rows=15 loops=1)

  Sort Key: t_zhld_ajdbxx.d_larq, t_zhld_ajdbxx.c_ajbh

  Sort Method: quicksort Memory: 2618kB

  -> Hash Semi Join (cost=2523.19..3223.63 rows=1 width=140) (actual time=55.913..107.265 rows=8605 loops=1)

   Hash Cond: ((t_zhld_ajdbxx.c_ajbh)::text = (t_zhld_zbajxx.c_ajbh)::text)

   -> Index Scan using i_t_zhld_ajdbxx_m6 on t_zhld_ajdbxx (cost=0.42..700.28 rows=219 width=140) (actual time=0.065..22.005 rows=8605 loops=1)

    Index Cond: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))

   -> Hash (cost=2513.84..2513.84 rows=714 width=32) (actual time=55.802..55.802 rows=8605 loops=1)

    Buckets: 16384 (originally 1024) Batches: 1 (originally 1) Memory Usage: 675kB

    -> HashAggregate (cost=2499.56..2506.70 rows=714 width=32) (actual time=30.530..43.275 rows=8605 loops=1)

    Group Key: t_zhld_zbajxx.c_ajbh

    -> Index Scan using i_t_zhld_zbajxx_h3 on t_zhld_zbajxx (cost=0.42..2497.77 rows=715 width=32) (actual time=0.043..15.552 rows=8605 loops=1)

     Index Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text))

 -> Index Scan using t_zhld_db_pkey on t_zhld_db (cost=0.28..8.30 rows=1 width=33) (actual time=0.009..0.011 rows=1 loops=15)

  Index Cond: (c_bh = t_zhld_ajdbxx.c_dbbh)
  Filter: (((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
Planning time: 1.154 ms
Execution time: 127.734 ms

这一次可以看出,ajdbxx和zbajxx表做了hash semi join 消除了nestedloop,cost降到了3231.97。并且使用上了i_t_zhld_ajdbxx_m6子查询中in的结果集有一万多条数据。

继续尝试使用exists等价改写in,看能否有更好的结果

2.4等价改写SQL(2)

等价改写:将in替换为exists:

select c_ajbh, c_ah, c_cbfy, c_cbrxm, d_larq, d_jarq, n_dbjg, c_yqlyfrom (select c_bh from db_zxzhld.t_zhld_db where n_state in (1,2,3) and c_dbztbh='1003' )dbxx
 join (select c_ajbh, c_ah, c_cbfy, c_cbrxm, d_larq, d_jarq, n_dbjg, c_yqly,c_dbbh from db_zxzhld.t_zhld_ajdbxx ajdbxxwhere c_zblx='1003'
 and c_dbfy='0' and c_gy = '2550' and
exists (select distinct c_ajbh from db_zxzhld.t_zhld_zbajxx zbajxx where ajdbxx.c_ajbh = zbajxx.c_ajbh and n_dbzt = 1 and c_zblx = '1003' and c_gy = '2550' ) order by d_larq asc, c_ajbh asc)dbajon dbxx.c_bh = dbaj.c_dbbh
 limit 15 offset 0

再次查看执行计划:

Limit (cost=1.12..2547.17 rows=1 width=107) (actual time=0.140..0.727 rows=15 loops=1)
 -> Nested Loop (cost=1.12..2547.17 rows=1 width=107) (actual time=0.136..0.689 rows=15 loops=1)
 -> Nested Loop Semi Join (cost=0.85..2538.84 rows=1 width=140) (actual time=0.115..0.493 rows=15 loops=1)
  -> Index Scan using i_t_zhld_ajdbxx_m6 on t_zhld_ajdbxx t2 (cost=0.42..700.28 rows=219 width=140) (actual time=0.076..0.127 rows=15 loops=1)
   Index Cond: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))
  -> Index Scan using i_t_zhld_zbajxx_c_ajbh on t_zhld_zbajxx t3 (cost=0.42..8.40 rows=1 width=32) (actual time=0.019..0.019 rows=1 loops=15)
   Index Cond: ((c_ajbh)::text = (t2.c_ajbh)::text)
   Filter: (((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text) AND (n_dbzt = 1))
 -> Index Scan using t_zhld_db_pkey on t_zhld_db (cost=0.28..8.30 rows=1 width=33) (actual time=0.007..0.008 rows=1 loops=15)
  Index Cond: (c_bh = t2.c_dbbh)
  Filter: (((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
Planning time: 1.268 ms
Execution time: 0.859 ms

可以看出使用exist效果更好,最终cost 2547.17

(1).少了t_zhld_zbajxx表的group by操作:Sort Key: t_zhld_ajdbxx.d_larq, t_zhld_ajdbxx.c_ajbh。(这一步是因为使用了索引中的排序)

(2).少了分组的操作:Group Key: t_zhld_zbajxx.c_ajbh。

第(2)为什么这个查询消除了t_zhld_zbajxx表的group by操作呢?

原因是exists替换了distinct的功能,一旦满足条件则立刻返回。所以使用exists的时候子查询可以直接去掉distinct。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • postgresql 计算距离的实例(单位直接生成米)

    之前用的是ST_Distance 函数,但是貌似需要进行一次单位的转换,而且网上有说那种转换不是特别准确,现在暂时将该算法记录在此: select st_distance(ST_GeomFromText('POINT(120.451737 36.520975)',900913),ST_GeomFromText('POINT(120.455636 36.520885)',900913))*60*1.852; 这里的计算方式倒是可以换坐标系,但是,测试了两个坐标系都没有起作用.而且该种方式转换过单位

  • PostgreSQL 性能优化之服务器参数配置操作

    大家好!我是只谈技术不剪发的 Tony 老师.今天我们来聊聊 PostgreSQL 的性能优化:数据库优化是一个系统的工程,本文只专注于服务器的参数配置优化. 默认安装时,PostgreSQL 的配置参数通常都偏小,不太适合作为生产服务器使用.所以,安装 PostgreSQL 数据库之后首先需要执行的操作就是对服务器的配置参数进行调整. 查看/设置参数值 我们使用 PostgreSQL 12,服务器的配置参数有 300 多个,运行时的参数值可以使用 SHOW 命令查看: show server_

  • postgresql 计算两点距离的2种方法小结

    postgresql计算两点距离 下面两种方法: select ST_Distance( ST_SetSRID(ST_MakePoint(115.97166453999147,28.716493914230423),4326)::geography, ST_SetSRID(ST_MakePoint(106.00231199774656,29.719258550486572),4326)::geography ), ST_Length( ST_MakeLine( ST_MakePoint(115.

  • postgresql 除法保留小数位的实例

    我就废话不多说了,大家还是直接看代码吧~ \x select 8/(100-3) as c1, round(8/(100-3) ,4) as c2, round(8/(100-3)::numeric ,4) as c3, 8/(100-3)::numeric as c4 ; -[ RECORD 1 ]-------------- c1 | 0 c2 | 0.0000 c3 | 0.0825 c4 | 0.08247422680412371134 (1 row) 补充:PostgreSQL整数除法

  • Postgresql 动态统计某一列的某一值出现的次数实例

    实例解析: select to_char(log.date, 'yyyy-MM-dd HH24') as hour, log.exten, sum(case log.grade when '1' then 1 else 0 end) as "1", sum(case log.grade when '2' then 1 else 0 end) as "2", sum(case log.grade when '3' then 1 else 0 end) as "

  • postgreSql分组统计数据的实现代码

    1. 背景 比如气象台的气温监控,每半小时上报一条数据,有很多个地方的气温监控,这样数据表里就会有很多地方的不同时间的气温数据 2. 需求: 每次查询只查最新的气温数据按照不同的温度区间来分组查出,比如:高温有多少地方,正常有多少地方,低温有多少地方 3. 构建数据 3.1 创建表结构: -- DROP TABLE public.t_temperature CREATE TABLE public.t_temperature ( id int4 NOT NULL GENERATED ALWAYS

  • Postgresql的select优化操作(快了200倍)

    对于庞大的数据,检索sql的编写要格外小心,有很多平时不注意的sql可能就会变成瓶颈. 比如, 我们有个系统, 其中t96_pd_log表,记录数8000w多,在开发阶段乃至用了那么多年都没问题, 最近却发生频繁死锁的问题, 查数据库后台发现问题出在一个select语句上, 它耗时高达2.4-2.7s,这对于一个需要高并发的系统来说当然是致命的. 数据表t96_pd_log有两条index, 一条的字段组成是f96_mgtbarcd,另一条的字段组成是f96_result_type, 检索sql

  • PostgreSQL删除更新优化操作

    1. 先说删除吧,因为刚搞了. 删除缓慢的原因:主要是约束的问题.(数据库在有约束的时候,进行操作,会根据约束对相关表进行验证,可想而知,20W的数据验证要耗费多久的时间).其次就是sql的编写.(sql如果查询中包含子查询等的可以优化的where会影响匹配的速度<查询的话就不多逼逼了>).索引的问题 请看下面的 补充部分 具体解决方法: ALTER TABLE tableName DISABLE TRIGGER ALL; delete 目标语句 ALTER TABLE tableName E

  • 使用imba.io框架得到比 vue 快50倍的性能基准

    我是标题党吗?是,但也不是.以图为证. 上图表示了vue, react 以及 imba 在 todo 这个项目中拥有60个 todoItem 不同进行 crud 操作的表现.可以看到 imba 达到了每秒操作5w次以上.如果你也想试一试该测试,可以访问Todos Bench.测试使用的是 Benchmark.js. imba 简单介绍 imba 是一种新的编程语言,可以编译为高性能的 JavaScript.可以直接用于 Web 编程(服务端与客户端)开发. 下面是语法: // 自定义标签 tag

  • 几行代码让 Python 函数执行快 30 倍

    目录 1.Python 多线程处理的基本指南 2.多处理入门 3.它为什么如此重要? 4.实现 5.基准测试 Python 是一种流行的编程语言,也是数据科学社区中最受欢迎的语言.与其他流行编程语言相比,Python 的主要缺点是它的动态特性和多功能属性拖慢了速度表现.Python 代码是在运行时被解释的,而不是在编译时被编译为原生代码. 1.Python 多线程处理的基本指南 C 语言的执行速度比 Python 代码快 10 到 100 倍.但如果对比开发速度的话,Python 比 C 语言要

  • 几行代码让 Python 函数执行快 30 倍

    目录 1.Python 多线程处理的基本指南 2.多处理入门 3.它为什么如此重要? 4.实现 5.基准测试 Python 是一种流行的编程语言,也是数据科学社区中最受欢迎的语言.与其他流行编程语言相比,Python 的主要缺点是它的动态特性和多功能属性拖慢了速度表现.Python 代码是在运行时被解释的,而不是在编译时被编译为原生代码. 1.Python 多线程处理的基本指南 C 语言的执行速度比 Python 代码快 10 到 100 倍.但如果对比开发速度的话,Python 比 C 语言要

  • 在PostgreSQL中实现递归查询的教程

     介绍 在Nilenso,哥在搞一个 (开源的哦!)用来设计和发起调查的应用. 下面这个是一个调查的例子: 在内部,它是这样表示滴: 一个调查包括了许多问题(question).一系列问题可以归到(可选)一个分类(category)中.我们实际的数据结构会复杂一点(特别是子问题sub-question部分),但先当它就只有question跟category吧. 我们是这样保存question跟category的. 每个question和category都有一个order_number字段.是个整

  • 改善你的jQuery的25个步骤 千倍级效率提升

    1. 从Google Code加载jQueryGoogle Code上已经托管了多种JavaScript类库,从Google Code上加载jQuery比直接从你的服务器加载更有优势.它节省了你服务器上的带宽,能够很快的从Google的内容分布网络(CDN)上加载JS类库.更重要的是,如果用户访问那些发布在Google Code上的站点后它会被缓存下来.这样做很有意义.有多少站点使用了没有被缓存的相同jQuery副本,而这些很容易做到,引入: <script type="text/java

  • mysql SELECT语句去除某个字段的重复信息

    SELECT语句,去除某个字段的重复信息,例如: 表名:table id uid username message dateline 1 6 a 111 1284240714(时间戳) 2 6 a 222 1268840565 3 8 b 444 1266724527 4 9 c 555 1266723391 执行语句(去除username字段重复信息并按时间排序): SELECT * FROM table a INNER JOIN ( SELECT max( dateline ) AS dat

  • MySQL全文索引、联合索引、like查询、json查询速度哪个快

    查询背景 有一个表tmp_test_course大概有10万条记录,然后有个json字段叫outline,存了一对多关系(保存了多个编码,例如jy1577683381775) 我们需要在这10万条数据中检索特定类型的数据,目标总数据量:2931条 SELECT COUNT(*) FROM tmp_test_course WHERE `type`=5 AND del=2 AND is_leaf=1 我们在限定为上面类型的同时,还得包含下面任意一个编码(也就是OR查询) jy157768338177

  • PostgreSQL的外部数据封装器fdw用法

    数据封装器fdw(Foreign Data Wrappers)在PostgreSQL中相当于oracle中的dblink,可以很方便的操作其他数据库中的数据. 场景,在本地的test库中通过外部数据封装器fdw访问本地的testdb中的t2表 本地库test用户u1,远程库test用户dbuser 版本: postgres=# select version(); version -----------------------------------------------------------

随机推荐