postgresql – WHERE子句是按照它们的写入顺序应用的吗?
我正在尝试优化查看大表(3700万行)的查询,并对查询中执行操作的顺序有疑问.
select 1 from workdays day where day.date_day >= '2014-10-01' and day.date_day <= '2015-09-30' and day.offer_id in ( select offer.offer_day from offer inner join province on offer.id_province = province.id_province inner join center cr on cr.id_cr = province.id_cr where upper(offer.code_status) <> 'A' and province.id_region in ('10','15','21','26','31',...,'557') and province.id_cr in ('9','14','20','25','30','35','37') ) 在子查询之前执行日期范围的WHERE子句吗? 现在查询需要花费很多时间来执行.
详细说明@ alci的答案:
PostgreSQL并不关心你写什么顺序 > PostgreSQL根本不关心WHERE子句中条目的顺序,只选择基于成本和选择性估计的索引和执行顺序. PostgreSQL将转换您的查询 PostgreSQL将严重转换查询,同时保留完全相同的效果,以便在不改变结果的情况下使它们运行得更快. >子查询之外的术语可以被推入子查询中,因此它们作为子查询的一部分执行,而不是在外部查询中编写它们的位置 通常,PostgreSQL可以大规模地转换和重写您的查询,以至于每个查询都是: select my_table.* from my_table left join other_table on (my_table.id = other_table.my_table_id) where other_table.id is null; select * from my_table where not exists ( select 1 from other_table where other_table.my_table_id = my_table.id ); select * from my_table where my_table.id not in ( select my_table_id from other_table where my_table_id is not null ); 通常会产生完全相同的查询计划. (假设我上面没有做出任何愚蠢的错误). 尝试优化查询只是为了发现查询计划程序已经找到了您正在尝试的技巧并自动应用它们,这种情况并不少见,因此手动优化版本并不比原始版本好. 限制 规划器/优化器远非全局,并且受限于绝对确定它不能改变查询效果,可用于决策的数据,已实施的规则以及CPU时间的要求.它可以花钱思考优化.例如: >计划员依赖于ANALYZE保存的统计数据(通常通过autovacuum).如果这些已经过时,那么计划选择可能会很糟糕. 吨也是. 您的查询 如果您的查询: select 1 from workdays day where day.date_day >= '2014-10-01' and day.date_day <= '2015-09-30' and day.offer_id in ( select offer.offer_day from offer inner join province on offer.id_province = province.id_province inner join center cr on cr.id_cr = province.id_cr where upper(offer.code_status) <> 'A' and province.id_region in ('10','37') ) 没有什么可以阻止它被平铺成一个带有额外连接集的简单查询,而且很可能会. 它可能会变成像(未经测试的,显然): select 1 from workdays day inner join offer on day.offer_id = offer.offer_day inner join province on offer.id_province = province.id_province inner join center cr on cr.id_cr = province.id_cr where upper(offer.code_status) <> 'A' and province.id_region in ('10','557') and province.id_cr in ('9','37') and day.date_day >= '2014-10-01' and day.date_day <= '2015-09-30'; 然后,PostgreSQL将根据其选择性和行计数估计值以及可用索引来优化连接顺序和连接方法.如果这些合理地反映了现实,那么它将进行连接并以最佳顺序运行where子句条目 – 通常将它们混合在一起,所以它做了一点,然后一点,然后回到第一部分等 如何查看优化器的功能 您无法看到PostgreSQL优化您的查询的SQL,因为它将SQL转换为内部查询树表示然后修改它.您可以转储查询计划并将其与其他查询进行比较. 没有办法将查询计划或内部计划树“解压缩”回SQL. http://explain.depesz.com/有一个不错的查询计划助手.如果你对查询计划等完全不熟悉(在这种情况下,我很惊讶你通过这篇文章做到了这一点),那么PgAdmin有一个图形查询计划查看器,它提供的信息少得多,但更简单. 相关阅读: > Optimizer 下推/上拉和展平功能continue to improve in each release. PostgreSQL通常适用于上拉/下推/展平决策,但并非总是如此,所以偶尔你必须(ab)使用CTE或OFFSET 0 hack.如果您发现这种情况,请报告查询计划程序错误. 如果你真的非常非常热衷于使用debug_print_plans选项来查看原始查询计划,但我保证你不想阅读它.真. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |