Planner不使用Check Constraints

时间:2013-10-11 21:07:27

标签: postgresql sql-execution-plan check-constraint

请考虑以下对象:

create table invoices_2011 (
  invoice_id bigint not null,
  invoice_date date not null,
  constraint invoice_line_2011_ck1 CHECK (invoice_date >= '2011-01-01' AND 
      invoice_date < '2012-01-01')
);

create table invoices_2012 (
  invoice_id bigint not null,
  invoice_date date not null,
  constraint invoice_line_2012_ck1 CHECK (invoice_date >= '2012-01-01' AND
      invoice_date < '2013-01-01')
);

create table invoices_2013 (
  invoice_id bigint not null,
  invoice_date date not null,
  constraint invoice_line_2013_ck1 CHECK (invoice_date >= '2013-01-01' AND
      invoice_date < '2014-01-01')
);

create or replace view invoices as
select * from invoices_2011
union all 
select * from invoices_2012
union all 
select * from invoices_2013;

如果我查看以下查询的解释计划:

select * from invoices where invoice_date > '2013-10-01';

它表示要扫描的唯一实际物理表是invoices_2013,这是我期望的。

但是,当我查看此查询的解释计划(今天是10/11/13)时:

select * from invoices where invoice_date > date_trunc ('month', current_date)

它扫描所有三个表。

是否有人知道以任何方式强制检查/插入函数,以便检查约束可以使用它?

1 个答案:

答案 0 :(得分:3)

问题是where子句必须与check constraint匹配。由于date_trunc()current_date都不是immutable,因此它们不会在查询中“内联”,这意味着这些函数评估只会在查询执行时,查询计划阶段之后发生,所以规划人员不知道条件是否与check constraint

匹配

为计划者提供所需的信息,必须动态构建查询

create or replace function select_from_invoices(
    _d date
) returns setof invoices as $body$

begin

return query execute $$
    select *
    from invoices
    where invoice_date > $1
    $$
    using date_trunc('month', _d)
;

end;
$body$ language plpgsql;

现在只有在date_trunc的结果连接到查询字符串后才会计划查询。

执行它:

select *
from select_from_invoices(current_date);