Dan*_*pka 4 sql postgresql exists limit
我写了查询
select * from table
where exists (select 1 from table1 where table.column = table1.column)
Run Code Online (Sandbox Code Playgroud)
如果我将其更改为
select * from table
where exists (select 1 from table1 where table.column = table1.column limit 1)
Run Code Online (Sandbox Code Playgroud)
它会改变逻辑吗?
我问是因为计划查询的费用已更改(17000-> 2400)。我使用Postgres 9.4
更新:解释分析两个查询的详细信息
explain (analyze, verbose)
select * from sr_srv_rendered r
where exists (select 1 from sr_res_group rg where rg.id = r.res_group_id and rg.responsible_id = 1)
limit 30
"Limit (cost=62.06..74.63 rows=30 width=157) (actual time=0.017..0.017 rows=0 loops=1)"
" Output: r.id, r.bdate, r.comment, r.cost, r.duration, r.edate, r.is_rendered, r.quantity, r.total_cost, r.contract_id, r.customer_id, r.funding_id, r.res_group_id, r.service_id, r.duration_measure_unit_id, r.begin_time, r.prototype_id, r.org_id, r.price_ (...)"
" -> Nested Loop (cost=62.06..287707.96 rows=686607 width=157) (actual time=0.017..0.017 rows=0 loops=1)"
" Output: r.id, r.bdate, r.comment, r.cost, r.duration, r.edate, r.is_rendered, r.quantity, r.total_cost, r.contract_id, r.customer_id, r.funding_id, r.res_group_id, r.service_id, r.duration_measure_unit_id, r.begin_time, r.prototype_id, r.org_id, r. (...)"
" -> Bitmap Heap Scan on public.sr_res_group rg (cost=61.62..10093.63 rows=2734 width=4) (actual time=0.017..0.017 rows=0 loops=1)"
" Output: rg.id, rg.bdate, rg.edate, rg.is_system, rg.name, rg.department_id, rg.org_id, rg.responsible_id, rg.is_available_in_electronic_queue, rg.label_id, rg.ignore_regclinic_check, rg.note, rg.blocked, rg.block_comment, rg.template_res_grou (...)"
" Recheck Cond: (rg.responsible_id = 1)"
" -> Bitmap Index Scan on responsible_fk (cost=0.00..60.94 rows=2734 width=0) (actual time=0.015..0.015 rows=0 loops=1)"
" Index Cond: (rg.responsible_id = 1)"
" -> Index Scan using fkb95967dd9f6b119a on public.sr_srv_rendered r (cost=0.43..99.03 rows=251 width=157) (never executed)"
" Output: r.id, r.bdate, r.comment, r.cost, r.duration, r.edate, r.is_rendered, r.quantity, r.total_cost, r.contract_id, r.customer_id, r.funding_id, r.res_group_id, r.service_id, r.duration_measure_unit_id, r.begin_time, r.prototype_id, r.org_ (...)"
" Index Cond: (r.res_group_id = rg.id)"
"Planning time: 0.931 ms"
"Execution time: 0.355 ms"
explain (analyze, verbose)
select * from sr_srv_rendered r
where exists (select 1 from sr_res_group rg where rg.id = r.res_group_id and rg.responsible_id = 1 limit 1)
limit 30
"Limit (cost=0.00..509.03 rows=30 width=157) (actual time=49392.352..49392.352 rows=0 loops=1)"
" Output: r.id, r.bdate, r.comment, r.cost, r.duration, r.edate, r.is_rendered, r.quantity, r.total_cost, r.contract_id, r.customer_id, r.funding_id, r.res_group_id, r.service_id, r.duration_measure_unit_id, r.begin_time, r.prototype_id, r.org_id, r.price_ (...)"
" -> Seq Scan on public.sr_srv_rendered r (cost=0.00..100177996.03 rows=5904050 width=157) (actual time=49392.340..49392.340 rows=0 loops=1)"
" Output: r.id, r.bdate, r.comment, r.cost, r.duration, r.edate, r.is_rendered, r.quantity, r.total_cost, r.contract_id, r.customer_id, r.funding_id, r.res_group_id, r.service_id, r.duration_measure_unit_id, r.begin_time, r.prototype_id, r.org_id, r. (...)"
" Filter: (SubPlan 1)"
" Rows Removed by Filter: 11062881"
" SubPlan 1"
" -> Limit (cost=0.43..8.46 rows=1 width=0) (actual time=0.004..0.004 rows=0 loops=11062881)"
" Output: (1)"
" -> Index Scan using sr_res_group_pk on public.sr_res_group rg (cost=0.43..8.46 rows=1 width=0) (actual time=0.003..0.003 rows=0 loops=11062881)"
" Output: 1"
" Index Cond: (rg.id = r.res_group_id)"
" Filter: (rg.responsible_id = 1)"
" Rows Removed by Filter: 1"
"Planning time: 0.694 ms"
"Execution time: 49392.495 ms"
Run Code Online (Sandbox Code Playgroud)
没有参数的情况下解释速度更快
小智 6
根据这些结果,不会更改高级逻辑(在两种情况下都返回相同,为空,返回set),但是更改计划会导致较大的性能差异。
似乎正在发生的事情是,PostgreSQL理解并且很乐意将第一种情况(在EXISTS内没有LIMIT)转换为嵌套循环联接,而在第二种情况下(在EXTISTS内有LIMIT),PostgreSQL不知道如何将其转换为联接(由于LIMIT)并使用幼稚的方法来实现它-在表中进行顺序扫描并为每一行运行子查询。
PostgreSQL理解EXISTS的工作原理,并且知道只需要查找一行,不需要添加“ LIMIT 1”,并且在这种情况下,实际上最终是有害的。
PostgreSQL可能会得到改进,以意识到EXISTS内部的LIMIT 1只是杂音,应该是没有意义的,但这会增加计划查询所需的时间,并且尚不清楚这种时间是否会花费很长时间。
| 归档时间: |
|
| 查看次数: |
1173 次 |
| 最近记录: |