• 售前

  • 售后

热门帖子
入门百科

postgresql通过索引优化查询速度操纵

[复制链接]
123457468 显示全部楼层 发表于 2021-10-26 12:23:28 |阅读模式 打印 上一主题 下一主题
当数据量比力大的时间,提拔查询效率就是必要去思量的事情了。一个百万级别的表格,如果不做任何优化的话,即使是最简单的查询语句执行起来也是慢的让人难以接受;当然“优化”自己是一个比力复杂的工程,从设计表、字段到查询语句的写法都有很多讲求,这里只思量索引的方式,且是最平凡的索引;
下面的操纵中对应数据库表w008_execrise_info(8000数据量), w008_wf02_info(4000数据量)
1 任务表数据
  1. SELECT
  2. w.*
  3. FROM
  4. w008_wf02_info w
  5. WHERE
  6. w.is_removed =0
  7. AND w.wfno = 'WF02'
  8. AND EXISTS (
  9. SELECT
  10. 1
  11. FROM
  12. w008_execrise_info info
  13. JOIN w008_privilege_allocation P ON (
  14. info.subjecttyp = P.subjecttyp
  15. AND info.gradetyp = P.gradetyp
  16. AND P.loginname = w.create_by
  17. AND P.verifyusers ='yixi_li'
  18. AND P.wftype = 20
  19. )
  20. WHERE
  21. info.is_removed =0
  22. AND info.wfid = w.wfid
  23. )
  24. ORDER BY
  25. create_date DESC
复制代码
执行结果:耗时在3秒左右(这个数据量,这个速率就比力慢了)

顺带说一句,这里把w.* 改成对应的字段也会稍微的进步一些查询速率(究竟少了一步把*转成对应字段的操纵),在标准的查询规范中也不会写成table.*这种方式的。
2 添加索引:

虽说索引可以进步查询速率,但是不代表加了索引就一定会加速查询速率,偶然以致会适得其反。
一样平常来说索引会加在where 后面的查询字段,尤其是关联字段上面,这里w008_execrise_info 表数据量最大,临时针对这个表举行处理;w008_execrise_info 表涉及四个字段:subjecttyp,gradetyp,wfid和is_removed。
此中is_removed先不思量,subjecttyp和gradetyp保存的是字典表的数据(数据内容比力少,雷同10 20 30 40),wfid保存的是数字范例的字符串。
一个索引起到的结果还取决于如许一个条件,一样平常来说添加索引的字段的值"唯一性"越明显越好,在这里,subjecttyp和gradetyp包罗大量的重复值,索引结果会“不明显”一些,而wfid 更像是“主键”,相对应的结果会好很多。
2.1 subjecttyp 和gradetyp添加索引
  1. CREATE INDEX w008_execrise_info_gradetyp_index ON w008_execrise_info (gradetyp);
  2. CREATE INDEX w008_execrise_info_subjecttyp_index ON w008_execrise_info (subjecttyp);
复制代码
添加后执行时间约莫2秒,快了一点点

2.2 对wfid添加索引
  1. CREATE INDEX w008_execrise_info_wfid_index ON w008_execrise_info (wfid);
复制代码
再次执行,0.2秒左右,快了很多

再补充一句,有很多情况下索引是不起作用的,比如 like后面跟的字段,还有条件语句or关联的字段,这种情况就是要思量查询策略了。
3 检察当前表的索引内容;
  1. select * from pg_indexes where tablename='w008_execrise_info';
复制代码
select * from pg_statio_all_indexes where relname='w008_execrise_info';

4 删除索引
  1. DROP INDEX indexName;
复制代码
5 重置索引

对于一些经常改动的表,如果时间长了发现查询效率变慢,可以思量重置一下索引;
因为如果表的内容被频仍的修改的话会产生许多雷同'索引碎片'的东西,会导致查询索引自己的时间变长;
  1. REINDEX INDEX index_name;//重置单个索引
  2. REINDEX TABLE table_name;//重置整个表的索引
  3. REINDEX DATABASE db_name;//终止整个数据库的所以你
复制代码
补充:PostgreSql查询优化之根据执行筹划优化SQL
1、执行筹划路径选择

postgresql查询规划过程中,查询请求的差别执行方案是通过创建差别的路径来表达的,在生成许多符合条件的路径之后,要从中选择出代价最小的路径(基于本钱运算),把它转化为一个筹划,转达给执行器执行,规划器的核心工作就是生成多条路径,然后从中找出最优的那一条。
1.1代价评估
评估路径优劣的依据是用体系表pg_statistic中的统计信息估算出来的差别路径的代价(cost),PostgreSQL估计筹划本钱的方式:基于统计信息估计筹划中各个节点的本钱。PostgreSQL会分析各个表来获取一个统计信息样本(这个操纵通常是由autovacuum这个保卫历程周期性的执行analyze,来收集这些统计信息,然后保存到pg_statistic和pg_class里面)。
1.2用于估算代价的参数postgresql.conf
  1. # - Planner Cost Constants -
  2. #seq_page_cost = 1.0  # measured on an arbitrary scale 顺序磁盘扫描时单个页面的开销
  3. #random_page_cost = 4.0  # same scale as above 随机磁盘访问时单页面的读取开销
  4. #cpu_tuple_cost = 0.01  # same scale as above cpu处理每一行的开销
  5. #cpu_index_tuple_cost = 0.005 # same scale as above cpu处理每个索引行的开销
  6. #cpu_operator_cost = 0.0025 # same scale as above cpu处理每个运算符或者函数调用的开销
  7. #parallel_tuple_cost = 0.1 # same scale as above 计算并行处理的成本,如果成本高于非并行,则不会开启并行处理。
  8. #parallel_setup_cost = 1000.0 # same scale as above
  9. #min_parallel_relation_size = 8MB
  10. #effective_cache_size = 4GB 再一次索引扫描中可用的文件系统内核缓冲区有效大小
复制代码
也可以利用 show all的方式检察
1.3 路径的选择
--检察表信息
  1. highgo=# \d t_jcxxgl_tjaj
  2.   Table "db_jcxx.t_jcxxgl_tjaj"
  3. Column |  Type  | Modifiers --------------+--------------------------------+-----------
  4. c_bh | character(32)   | not null
  5. c_xzdm | character varying(300)  |
  6. c_jgid | character(32)   |
  7. c_ajbm | character(22)   |
  8. ...
  9. Indexes:
  10. "t_jcxxgl_tjaj_pkey" PRIMARY KEY, btree (c_bh)
  11. "idx_ttjaj_cah" btree (c_ah)
  12. "idx_ttjaj_dslrq" btree (d_slrq)
复制代码
起首更新统计信息vacuum analyze t_jcxxgl_tjaj,许多时间大概因为统计信息的禁绝确导致了不正常的执行筹划--执行筹划。
--执行筹划,全表扫描
  1. 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';
  2.        QUERY PLAN      ------------------------------------------------------------------------------------------------------------
  3. 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
  4. =1)
  5. Output: c_bh, c_xzdm, c_jgid, c_ajbm
  6. Filter: (t_jcxxgl_tjaj.d_slrq >= '2018-03-18'::date)
  7. Rows Removed by Filter: 138
  8. Buffers: shared hit=8
  9. Planning time: 6.579 ms
  10. Execution time: 1.163 ms
  11. (7 rows)
复制代码
如上,d_slrq是有索引的,但是执行筹划中并没有走索引,为什么呢?我们继承往下看。
--执行筹划,关闭全表扫描
  1. highgo=# set session enable_seqscan = off;
  2. SET
  3. 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';
  4.         QUERY PLAN        ------------------------------------------------------------------------------------------------------------
  5. 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)
  6. Output: c_bh, c_xzdm, c_jgid, c_ajbm
  7. Index Cond: (t_jcxxgl_tjaj.d_slrq >= '2018-03-18'::date)
  8. Buffers: shared hit=4
  9. Planning time: 0.309 ms
  10. Execution time: 0.063 ms
  11. (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列中。我们可以如许查询干系信息:
​--检察统计信息
  1. highgo=# select relpages,reltuples from pg_class where relname ='t_jcxxgl_tjaj';
  2. relpages | reltuples ----------+-----------
  3. 8 | 141
  4. (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:
  1. 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的表的数据量:
  1.   t_zhld_db :1311
  2.   t_zhld_ajdbxx :341296
  3. t_zhld_zbajxx :1027619
复制代码
执行筹划:
  1. Limit (cost=36328.67..36328.68 rows=1 width=107) (actual time=88957.677..88957.729 rows=15 loops=1)
  2. -> Sort (cost=36328.67..36328.68 rows=1 width=107) (actual time=88957.653..88957.672 rows=15 loops=1)
  3.   Sort Key: dbaj.d_larq, dbaj.c_ajbh
  4.   Sort Method: top-N heapsort Memory: 27kB
  5.   -> Nested Loop Semi Join (cost=17099.76..36328.66 rows=1 width=107) (actual time=277.794..88932.662 rows=8605 loops=1)
  6.   Join Filter: ((dbaj.c_ajbh)::text = (t_zhld_zbajxx.c_ajbh)::text)
  7.   Rows Removed by Join Filter: 37018710
  8.   -> Nested Loop (cost=0.00..19200.59 rows=1 width=107) (actual time=199.141..601.845 rows=8605 loops=1)
  9.    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等逻辑外键的索引
  1. drop index if exists I_T_ZHLD_AJDBXX_AJBH;
  2. create index I_T_ZHLD_AJDBXX_AJBH on T_ZHLD_AJDBXX (c_ajbh);
  3. commit;
  4. drop index if exists I_T_ZHLD_AJDBXX_DBBH;
  5. create index I_T_ZHLD_AJDBXX_DBBH on T_ZHLD_AJDBXX (c_dbbh);
  6. commit;
复制代码
创建d_larq,c_ajbh的排序索引:
  1. 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);
  2. commit;
  3. drop index if exists I_T_ZHLD_ZBAJXX_h3 ;
  4. create index I_T_ZHLD_ZBAJXX_h3 on db_zxzhld.t_zhld_zbajxx (n_dbzt,c_zblx,c_gy,c_gy);
  5. commit;
复制代码
创建索引后执行筹划有了改变,原来的dbaj表和dbxx表先做nestedloop酿成了zbaj和dbaj表先做了nestedloop join,总的cost也从36328.68降到了12802.87,
执行筹划
  1. Limit (cost=12802.87..12802.87 rows=1 width=107) (actual time=4263.598..4263.648 rows=15 loops=1)
  2. -> Sort (cost=12802.87..12802.87 rows=1 width=107) (actual time=4263.592..4263.609 rows=15 loops=1)
  3. Sort Key: dbaj.d_larq, dbaj.c_ajbh
  4. Sort Method: top-N heapsort Memory: 27kB
  5. -> Nested Loop (cost=2516.05..12802.86 rows=1 width=107) (actual time=74.240..4239.723 rows=8605 loops=1)
  6.   Join Filter: (dbaj.c_dbbh = dbxx.c_bh)
  7.   Rows Removed by Join Filter: 111865
  8.   -> Nested Loop (cost=2516.05..12736.34 rows=1 width=140) (actual time=74.083..327.974 rows=8605 loops=1)
  9.    -> HashAggregate (cost=2515.62..2522.76 rows=714 width=32) (actual time=74.025..90.185 rows=8605 loops=1)
  10.     Group Key: ("ANY_subquery".c_ajbh)::text
  11.     -> Subquery Scan on "ANY_subquery" (cost=2499.56..2513.84 rows=714 width=32) (actual time=28.782..59.823 rows=8605 loops=1)
  12.     -> HashAggregate (cost=2499.56..2506.70 rows=714 width=32) (actual time=28.778..39.968 rows=8605 loops=1)
  13.      Group Key: zbaj.c_ajbh
  14.      -> 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)
  15.       Index Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text))
  16.    -> 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)
  17.     Index Cond: ((c_ajbh)::text = ("ANY_subquery".c_ajbh)::text)
  18.     Filter: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))
  19.     Rows Removed by Filter: 1
  20.   -> 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)
  21.    Filter: ((n_valid = 1) AND ((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
  22.    Rows Removed by Filter: 1298
  23. Planning time: 1.075 ms
  24. Execution time: 4263.803 ms
复制代码
执行的时间还是要4s左右仍旧不满足需求,而且没有利用上I_T_ZHLD_AJDBXX_m6这个索引。
2.3等价改写SQL(1)
等价改写:将排序条件参加db_zxzhld.t_zhld_ajdbxx让其先排序,再和t_zhld_db表连接。
修改后sql:
  1. 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
  2. join (select * from db_zxzhld.t_zhld_ajdbxx where n_valid=1 and c_zblx='1003'
  3. and c_dbfy='0' and c_gy = '2550' and
  4. 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
  5. limit 15 offset 0
复制代码
再次检察执行筹划:
  1. Limit (cost=3223.92..3231.97 rows=1 width=107) (actual time=127.291..127.536 rows=15 loops=1)
  2. -> Nested Loop (cost=3223.92..3231.97 rows=1 width=107) (actual time=127.285..127.496 rows=15 loops=1)
  3. -> Sort (cost=3223.64..3223.65 rows=1 width=140) (actual time=127.210..127.225 rows=15 loops=1)
  4.   Sort Key: t_zhld_ajdbxx.d_larq, t_zhld_ajdbxx.c_ajbh
  5.   Sort Method: quicksort Memory: 2618kB
  6.   -> Hash Semi Join (cost=2523.19..3223.63 rows=1 width=140) (actual time=55.913..107.265 rows=8605 loops=1)
  7.    Hash Cond: ((t_zhld_ajdbxx.c_ajbh)::text = (t_zhld_zbajxx.c_ajbh)::text)
  8.    -> 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)
  9.     Index Cond: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))
  10.    -> Hash (cost=2513.84..2513.84 rows=714 width=32) (actual time=55.802..55.802 rows=8605 loops=1)
  11.     Buckets: 16384 (originally 1024) Batches: 1 (originally 1) Memory Usage: 675kB
  12.     -> HashAggregate (cost=2499.56..2506.70 rows=714 width=32) (actual time=30.530..43.275 rows=8605 loops=1)
  13.     Group Key: t_zhld_zbajxx.c_ajbh
  14.     -> 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)
  15.      Index Cond: ((n_dbzt = 1) AND ((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text))
  16. -> 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)
  17.   Index Cond: (c_bh = t_zhld_ajdbxx.c_dbbh)
  18.   Filter: (((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
  19. Planning time: 1.154 ms
  20. 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:
  1. 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
  2. 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'
  3. and c_dbfy='0' and c_gy = '2550' and
  4. 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
  5. limit 15 offset 0
复制代码
再次检察执行筹划:
  1. Limit (cost=1.12..2547.17 rows=1 width=107) (actual time=0.140..0.727 rows=15 loops=1)
  2. -> Nested Loop (cost=1.12..2547.17 rows=1 width=107) (actual time=0.136..0.689 rows=15 loops=1)
  3. -> Nested Loop Semi Join (cost=0.85..2538.84 rows=1 width=140) (actual time=0.115..0.493 rows=15 loops=1)
  4.   -> 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)
  5.    Index Cond: (((c_zblx)::text = '1003'::text) AND ((c_dbfy)::text = '0'::text) AND ((c_gy)::text = '2550'::text))
  6.   -> 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)
  7.    Index Cond: ((c_ajbh)::text = (t2.c_ajbh)::text)
  8.    Filter: (((c_zblx)::text = '1003'::text) AND ((c_gy)::text = '2550'::text) AND (n_dbzt = 1))
  9. -> 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)
  10.   Index Cond: (c_bh = t2.c_dbbh)
  11.   Filter: (((c_dbztbh)::text = '1003'::text) AND (n_state = ANY ('{1,2,3}'::integer[])))
  12. Planning time: 1.268 ms
  13. 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。
以上为个人经验,希望能给各人一个参考,也希望各人多多支持草根技能分享。如有错误或未思量完全的地方,望不吝赐教。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作