2

次のオブジェクトを考慮してください。

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)

3 つのテーブルすべてをスキャンします。

チェック制約がそれを利用できるように、関数の検査/補間を強制する方法を知っている人はいますか?

4

1 に答える 1

3

問題は、where句がcheck constraint. どちらdate_trunc()不変current_dateであるため、クエリで「インライン化」されません。つまり、これらの関数の評価は、クエリ計画段階の後、クエリの実行時にのみ行われるため、プランナは条件が一致するかどうかを知りません。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);
于 2013-10-11T22:55:04.740 に答える