Планировщик не использует проверку ограничений
Пожалуйста, рассмотрите следующие объекты:
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 ответ
Проблема в том, что 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);