2

考虑以下结构,标题和行表,它们都按日期分区:

create table stage.order_header (
  order_id    int   not null,
  order_date  date  not null
);

create table stage.order_line (
  order_id     int   not null,
  order_date   date  not null,
  order_line   int   not null
);

create table stage.order_header_2013 (
  constraint order_header_2013_ck1
    check (order_date >= '2013-01-01' and order_date < '2014-01-01')
) inherits (stage.order_header);

create table stage.order_header_2014 (
  constraint order_header_2014_ck1
    check (order_date >= '2014-01-01' and order_date < '2015-01-01')
) inherits (stage.order_header);

create table stage.order_line_2013 (
  constraint order_line_2013_ck1
    check (order_date >= '2013-01-01' and order_date < '2014-01-01')
) inherits (stage.order_line);

create table stage.order_line_2014 (
  constraint order_line_2014_ck1
    check (order_date >= '2014-01-01' and order_date < '2015-01-01')
) inherits (stage.order_line);

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

select
  *
from
  stage.order_header h
  join stage.order_line l on
    h.order_id = l.order_id and
    h.order_date = l.order_date
where
  h.order_date = '2014-04-01'

它同时调用检查约束并且仅物理扫描“2014”分区。

但是,如果我使用不等式:

where
  h.order_date > '2014-04-01' and
  h.order_date < '2014-05-01'

检查约束在表头上调用,但不在行上,查询将扫描整个 line_2013 表,即使记录不存在。我的想法是,由于 order_date 包含在联接中,因此一个表中对其的任何限制都会传播到联接表,但情况似乎并非如此。

如果我明确表示:

where
  h.order_date > '2014-04-01' and
  h.order_date < '2014-05-01' and
  l.order_date > '2014-04-01' and
  l.order_date < '2014-05-01'

然后一切都按预期工作。

我的问题是:我现在知道这一点,并且可以在 where 子句中添加额外的限制,但我担心的是其他所有人都在使用不知道这样做的数据库。我是否可以进行结构(或其他)更改来解决此问题?我尝试添加外键约束,但这并没有改变计划。

此外,查询本身实际上是在物理扫描 2013 表。这不仅仅是解释计划。

编辑:

我确实将此提交给错误,但似乎这种行为不太可能改变......这就是促使我看到解决方法的原因。

对我的报告的回应是:

如果我专门在 h 和 l 表上调用范围,它将正常工作,但由于连接指定这些字段必须相同,该条件可以自动传播吗?


不。我们目前推断出相等性,因此规划器能够从您的查询中提取约束 l.transaction_date = '2014-03-01' (然后使用它来推断 l 的孩子的检查约束)。但是对于不等式没有可比性,并且不清楚将这样的逻辑添加到规划器中是否会是一个净赢。它会比相等的情况更复杂,也不太有用。

4

0 回答 0