zoukankan      html  css  js  c++  java
  • postgresql遇到的性能问题

    问题SQL

    scwksmlcls.wk_cls_c
    , scwklrgcls.wk_lrg_cls_nm
    , scwkmdlcls.wk_mdl_cls_nm
    , scwksmlcls.wk_sml_cls_nm
    , scwksmlcls.wk_cls_rmk
    FROM
    screqrsnsws
    INNER JOIN scwkclsreqrsnsws
    ON scwkclsreqrsnsws.req_rsn_id = screqrsnsws.req_rsn_id
    INNER JOIN scwksmlcls
    ON scwksmlcls.wk_sml_cls_id = scwkclsreqrsnsws.wk_sml_cls_id
    AND scwksmlcls.wk_sml_cls_id_ek IS NOT NULL
    INNER JOIN scwkmdlcls
    ON scwkmdlcls.wk_mdl_cls_id = scwksmlcls.wk_mdl_cls_id
    AND scwkmdlcls.wk_lrg_cls_id = scwksmlcls.wk_lrg_cls_id
    AND scwkmdlcls.wk_mdl_cls_id_ek IS NOT NULL
    INNER JOIN scwklrgcls
    ON scwklrgcls.wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id
    AND scwklrgcls.wk_lrg_cls_id_ek IS NOT NULL
    WHERE
    screqrsnsws.req_rsn_c = '996N'
    AND scwksmlcls.wk_cls_c = '112233'
    AND screqrsnsws.req_rsn_id_ek IS NOT NULL
    ORDER BY
    scwklrgcls.disp_odr
    , scwkmdlcls.disp_odr
    , scwksmlcls.disp_odr

    -- 用到的表

    select count(*) from screqrsnsws; --依赖理由 件数:58

    select count(*) from scwkclsreqrsnsws; --依頼理由分類 件数:289142

    select count(*) from scwksmlcls; -- 小分類 件数:289414

    select count(*) from scwkmdlcls; -- 中分類 件数:285223

    select count(*) from scwklrgcls; -- 大分類 件数:1962


    表定义
    create table score.screqrsnsws (
    req_rsn_id integer not null
    , req_rsn_id_ek integer
    , req_rsn_c character varying(4) not null
    , req_rsn_nm character varying(20) not null
    , fix_assts_tagt_f character varying(1) not null
    , pms_i_ymd timestamp without time zone default now() not null
    , pms_i_usr character varying(32) default "current_user"() not null
    , pms_i_class character varying(128)
    , pms_u_ymd timestamp without time zone
    , pms_u_usr character varying(32)
    , pms_u_class character varying(128)
    , primary key (req_rsn_id)
    );

    req_rsn_id、req_rsn_c、req_rsn_id_ek のindex

    create table score.scwkclsreqrsnsws (
    req_rsn_id integer not null
    , wk_sml_cls_id integer not null
    , drct_ind_h_k character varying(1) not null
    , pms_i_ymd timestamp without time zone default now() not null
    , pms_i_usr character varying(32) default "current_user"() not null
    , pms_i_class character varying(128)
    , pms_u_ymd timestamp without time zone
    , pms_u_usr character varying(32)
    , pms_u_class character varying(128)
    , primary key (req_rsn_id,wk_sml_cls_id)
    );

    req_rsn_id,wk_sml_cls_idの複合index
    req_rsn_id

    create table score.scwksmlcls (
    wk_sml_cls_id integer not null
    , wk_sml_cls_id_ek integer
    , work_lrg_cls_c character varying(2) not null
    , wk_mdl_cls_c character varying(2) not null
    , wk_sml_cls_c character varying(2) not null
    , wk_cls_c character varying(6) not null
    , wk_sml_cls_nm character varying(50) not null
    , disp_odr integer
    , wk_cls_rmk character varying(200)
    , pg_dev_hndl_f character varying(1) not null
    , fix_assts_tagt_f character varying(1) not null
    , pms_i_ymd timestamp without time zone default now() not null
    , pms_i_usr character varying(32) default "current_user"() not null
    , pms_i_class character varying(128)
    , pms_u_ymd timestamp without time zone
    , pms_u_usr character varying(32)
    , pms_u_class character varying(128)
    , wk_dept_c character varying(4)
    , wk_lrg_cls_id integer
    , wk_mdl_cls_id integer
    , primary key (wk_sml_cls_id)
    );

    wk_sml_cls_id,
    work_lrg_cls_c,wk_mdl_cls_c,wk_sml_cls_c复合索引
    wk_cls_c
    wk_sml_cls_id_ek


    create table score.scwkmdlcls (
    wk_mdl_cls_id integer not null
    , wk_mdl_cls_id_ek integer
    , work_lrg_cls_c character varying(2) not null
    , wk_mdl_cls_c character varying(2) not null
    , wk_mdl_cls_nm character varying(50) not null
    , disp_odr integer
    , wk_lrg_cls_id integer
    , wk_dept_c character varying(4)
    , pms_i_ymd timestamp without time zone default now() not null
    , pms_i_usr character varying(32) default "current_user"() not null
    , pms_i_class character varying(128)
    , pms_u_ymd timestamp without time zone
    , pms_u_usr character varying(32)
    , pms_u_class character varying(128)
    , primary key (wk_mdl_cls_id)
    );

    wk_mdl_cls_id
    work_lrg_cls_c,wk_mdl_cls_c
    wk_mdl_cls_id_ek


    create table score.scwklrgcls (
    wk_lrg_cls_id integer not null
    , wk_lrg_cls_id_ek integer
    , work_lrg_cls_c character varying(2) not null
    , wk_lrg_cls_nm character varyin g 

    通过SQL语句前加"EXPLAIN ANALYZE"执行SQL得到的执行计划

    QUERY PLAN
    Sort (cost=3589.88..3589.89 rows=1 width=96) (actual time=21816.121..21816.121 rows=1 loops=1)
    Sort Key: scwklrgcls.disp_odr, scwkmdlcls.disp_odr, scwksmlcls.disp_odr
    Sort Method: quicksort Memory: 25kB
    -> Nested Loop (cost=557.47..3589.87 rows=1 width=96) (actual time=11548.596..21816.102 rows=1 loops=1)
    -> Nested Loop (cost=557.47..3585.59 rows=1 width=80) (actual time=11548.550..21816.055 rows=1 loops=1)
    Join Filter: (scwkclsreqrsnsws.req_rsn_id = screqrsnsws.req_rsn_id)
    -> Nested Loop (cost=557.47..3585.31 rows=1 width=84) (actual time=1.472..21798.988 rows=4401 loops=1)
    -> Hash Join (cost=557.47..1413.63 rows=1 width=84) (actual time=1.453..15.100 rows=4401 loops=1)
    Hash Cond: ((scwksmlcls.wk_mdl_cls_id = scwkmdlcls.wk_mdl_cls_id) AND (scwksmlcls.wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id))
    -> Index Scan using i_scwksmlcls_ek on scwksmlcls (cost=0.00..823.09 rows=4408 width=55) (actual time=0.013..4.404 rows=4401 loops=1)
    Index Cond: (wk_sml_cls_id_ek IS NOT NULL)
    -> Hash (cost=540.67..540.67 rows=1120 width=37) (actual time=1.420..1.420 rows=1124 loops=1)
    Buckets: 1024 Batches: 1 Memory Usage: 73kB
    -> Index Scan using i_scwkmdlcls_ek on scwkmdlcls (cost=0.00..540.67 rows=1120 width=37) (actual time=0.047..1.051 rows=1124 loops=1)
    Index Cond: (wk_mdl_cls_id_ek IS NOT NULL)
    -> Index Scan using con_scwkclsreqrsnsws_pri on scwkclsreqrsnsws (cost=0.00..2171.67 rows=1 width=8) (actual time=1.140..4.948 rows=1 loops=4401)
    Index Cond: (wk_sml_cls_id = scwksmlcls.wk_sml_cls_id)
    -> Index Scan using i_screqrsnsws_alt2 on screqrsnsws (cost=0.00..0.27 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=4401)
    Index Cond: ((req_rsn_c)::text = '996N'::text)
    Filter: (req_rsn_id_ek IS NOT NULL)
    -> Index Scan using con_scwklrgcls_pri on scwklrgcls (cost=0.00..4.27 rows=1 width=28) (actual time=0.011..0.012 rows=1 loops=1)
    Index Cond: (wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id)
    Filter: (wk_lrg_cls_id_ek IS NOT NULL)
    Total runtime: 21816.279 ms

    看了表的定义,索引,执行计划,认为小分类表和中分类表INNERJOIN的条件「AND scwkmdlcls.wk_lrg_cls_id = scwksmlcls.wk_lrg_cls_id」多余。

    因为大中小分类表的主键是ID,用主键ID连接应该足够了。去掉此条件的执行时间会明显加快。

    EXPLAIN ANALYZE SELECT
    scwksmlcls.wk_cls_c
    , scwklrgcls.wk_lrg_cls_nm
    , scwkmdlcls.wk_mdl_cls_nm
    , scwksmlcls.wk_sml_cls_nm
    , scwksmlcls.wk_cls_rmk
    FROM
    screqrsnsws
    INNER JOIN scwkclsreqrsnsws
    ON scwkclsreqrsnsws.req_rsn_id = screqrsnsws.req_rsn_id
    INNER JOIN scwksmlcls
    ON scwksmlcls.wk_sml_cls_id = scwkclsreqrsnsws.wk_sml_cls_id
    AND scwksmlcls.wk_sml_cls_id_ek IS NOT NULL
    INNER JOIN scwkmdlcls
    ON scwkmdlcls.wk_mdl_cls_id = scwksmlcls.wk_mdl_cls_id
    -- AND scwkmdlcls.wk_lrg_cls_id = scwksmlcls.wk_lrg_cls_id
    AND scwkmdlcls.wk_mdl_cls_id_ek IS NOT NULL
    INNER JOIN scwklrgcls
    ON scwklrgcls.wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id
    AND scwklrgcls.wk_lrg_cls_id_ek IS NOT NULL
    WHERE
    screqrsnsws.req_rsn_c = '996N'
    AND scwksmlcls.wk_cls_c = '112233'
    AND screqrsnsws.req_rsn_id_ek IS NOT NULL
    ORDER BY
    scwklrgcls.disp_odr
    , scwkmdlcls.disp_odr
    , scwksmlcls.disp_odr


    QUERY PLAN
    Sort (cost=5598.19..5598.20 rows=1 width=96) (actual time=3.270..3.270 rows=1 loops=1)
    Sort Key: scwklrgcls.disp_odr, scwkmdlcls.disp_odr, scwksmlcls.disp_odr
    Sort Method: quicksort Memory: 25kB
    -> Nested Loop (cost=949.97..5598.18 rows=1 width=96) (actual time=3.254..3.260 rows=1 loops=1)
    -> Nested Loop (cost=949.97..5597.80 rows=1 width=76) (actual time=3.245..3.249 rows=1 loops=1)
    -> Hash Join (cost=949.97..5429.77 rows=77 width=47) (actual time=3.237..3.241 rows=1 loops=1)
    Hash Cond: (scwkclsreqrsnsws.wk_sml_cls_id = scwksmlcls.wk_sml_cls_id)
    -> Nested Loop (cost=71.78..4512.75 rows=5075 width=4) (actual time=0.038..0.041 rows=1 loops=1)
    -> Seq Scan on screqrsnsws (cost=0.00..2.71 rows=1 width=4) (actual time=0.023..0.025 rows=1 loops=1)
    Filter: ((req_rsn_id_ek IS NOT NULL) AND ((req_rsn_c)::text = '996N'::text))
    -> Bitmap Heap Scan on scwkclsreqrsnsws (cost=71.78..4443.07 rows=5357 width=8) (actual time=0.012..0.012 rows=1 loops=1)
    Recheck Cond: (req_rsn_id = screqrsnsws.req_rsn_id)
    -> Bitmap Index Scan on con_scwkclsreqrsnsws_pri (cost=0.00..70.44 rows=5357 width=0) (actual time=0.008..0.008 rows=1 loops=1)
    Index Cond: (req_rsn_id = screqrsnsws.req_rsn_id)
    -> Hash (cost=823.09..823.09 rows=4408 width=51) (actual time=3.186..3.186 rows=4401 loops=1)
    Buckets: 1024 Batches: 1 Memory Usage: 313kB
    -> Index Scan using i_scwksmlcls_ek on scwksmlcls (cost=0.00..823.09 rows=4408 width=51) (actual time=0.011..2.002 rows=4401 loops=1)
    Index Cond: (wk_sml_cls_id_ek IS NOT NULL)
    -> Index Scan using con_scwkmdlcls_pri on scwkmdlcls (cost=0.00..2.17 rows=1 width=37) (actual time=0.005..0.005 rows=1 loops=1)
    Index Cond: (wk_mdl_cls_id = scwksmlcls.wk_mdl_cls_id)
    Filter: (wk_mdl_cls_id_ek IS NOT NULL)
    -> Index Scan using con_scwklrgcls_pri on scwklrgcls (cost=0.00..0.37 rows=1 width=28) (actual time=0.009..0.009 rows=1 loops=1)
    Index Cond: (wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id)
    Filter: (wk_lrg_cls_id_ek IS NOT NULL)
    Total runtime: 3.364 ms

    postgresql和oracle的执行计划还真是不一样。

    另外还发现有意思的事情,业务上“screqrsnsws.req_rsn_c = scwksmlcls.wk_dept_c”这个是成立的,加入这个条件后语句也能变快,原因是WHERE条件里的"screqrsnsws.req_rsn_c = '996N' "的条件,执行计划里会"scwksmlcls.wk_dept_c = '996N'",内层表的选取数据变小。

    EXPLAIN ANALYZE
    SELECT
    scwksmlcls.wk_cls_c
    , scwklrgcls.wk_lrg_cls_nm
    , scwkmdlcls.wk_mdl_cls_nm
    , scwksmlcls.wk_sml_cls_nm
    , scwksmlcls.wk_cls_rmk
    FROM
    screqrsnsws
    INNER JOIN scwkclsreqrsnsws
    ON scwkclsreqrsnsws.req_rsn_id = screqrsnsws.req_rsn_id
    AND screqrsnsws.req_rsn_id_ek IS NOT NULL
    INNER JOIN scwksmlcls
    ON scwksmlcls.wk_sml_cls_id = scwkclsreqrsnsws.wk_sml_cls_id
    AND screqrsnsws.req_rsn_c = scwksmlcls.wk_dept_c
    AND scwksmlcls.wk_sml_cls_id_ek IS NOT NULL
    INNER JOIN scwkmdlcls
    ON scwkmdlcls.wk_mdl_cls_id = scwksmlcls.wk_mdl_cls_id
    AND scwkmdlcls.wk_lrg_cls_id = scwksmlcls.wk_lrg_cls_id
    AND scwkmdlcls.wk_mdl_cls_id_ek IS NOT NULL
    INNER JOIN scwklrgcls
    ON scwklrgcls.wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id
    AND scwklrgcls.wk_lrg_cls_id_ek IS NOT NULL
    WHERE
    screqrsnsws.req_rsn_c = '996N'
    AND screqrsnsws.req_rsn_id_ek IS NOT NULL
    ORDER BY
    scwklrgcls.disp_odr
    , scwkmdlcls.disp_odr
    , scwksmlcls.disp_odr

    QUERY PLAN
    Sort (cost=859.96..859.97 rows=1 width=96) (actual time=2.025..2.025 rows=1 loops=1)
    Sort Key: scwklrgcls.disp_odr, scwkmdlcls.disp_odr, scwksmlcls.disp_odr
    Sort Method: quicksort Memory: 25kB
    -> Nested Loop (cost=0.00..859.95 rows=1 width=96) (actual time=1.050..2.013 rows=1 loops=1)
    Join Filter: (scwksmlcls.wk_lrg_cls_id = scwkmdlcls.wk_lrg_cls_id)
    -> Nested Loop (cost=0.00..855.66 rows=1 width=79) (actual time=1.041..2.003 rows=1 loops=1)
    -> Nested Loop (cost=0.00..851.35 rows=1 width=87) (actual time=1.012..1.974 rows=1 loops=1)
    -> Index Scan using con_screqrsnsws_pri on screqrsnsws (cost=0.00..8.68 rows=1 width=9) (actual time=0.015..0.030 rows=1 loops=1)
    Filter: ((req_rsn_id_ek IS NOT NULL) AND (req_rsn_id_ek IS NOT NULL) AND ((req_rsn_c)::text = '996N'::text))
    -> Nested Loop (cost=0.00..842.67 rows=1 width=88) (actual time=0.995..1.942 rows=1 loops=1)
    -> Index Scan using i_scwksmlcls_ek on scwksmlcls (cost=0.00..834.11 rows=2 width=60) (actual time=0.988..1.934 rows=1 loops=1)
    Index Cond: (wk_sml_cls_id_ek IS NOT NULL)
    Filter: ((wk_dept_c)::text = '996N'::text)
    -> Index Scan using con_scwklrgcls_pri on scwklrgcls (cost=0.00..4.27 rows=1 width=28) (actual time=0.004..0.005 rows=1 loops=1)
    Index Cond: (wk_lrg_cls_id = scwksmlcls.wk_lrg_cls_id)
    Filter: (wk_lrg_cls_id_ek IS NOT NULL)
    -> Index Scan using con_scwkclsreqrsnsws_pri on scwkclsreqrsnsws (cost=0.00..4.29 rows=1 width=8) (actual time=0.028..0.028 rows=1 loops=1)
    Index Cond: ((req_rsn_id = screqrsnsws.req_rsn_id) AND (wk_sml_cls_id = scwksmlcls.wk_sml_cls_id))
    -> Index Scan using con_scwkmdlcls_pri on scwkmdlcls (cost=0.00..4.28 rows=1 width=37) (actual time=0.005..0.006 rows=1 loops=1)
    Index Cond: (wk_mdl_cls_id = scwksmlcls.wk_mdl_cls_id)
    Filter: (wk_mdl_cls_id_ek IS NOT NULL)
    Total runtime: 2.143 ms

     为了能大概看懂这执行计划,还特意搜索了一下"postgresql的explain命令详解",那个挺有用。

  • 相关阅读:
    8位单片机可用的 mktime localtime函数
    【转载】linux获取mac地址
    【转载】openwrt框架分析
    JVM调优工具Arthas的使用
    Grafana监控JVM
    JAVA死锁排查-性能测试问题排查思路
    JVM的堆内存泄漏排查-性能测试
    性能测试之JVM的故障分析工具VisualVM
    性能测试之 JVM 异常说明和分析工具
    性能测试之 JVM 概念认识
  • 原文地址:https://www.cnblogs.com/zhuqingkfv/p/postgresql1.html
Copyright © 2011-2022 走看看