1

我一直在阅读文档并查看常见问题解答,但尚未找到此问题的答案,这可能意味着无法完成。我的实际情况稍微复杂一些,但我会尽量简化这个问题。对于过去的每一年,我都有一个标题/详细信息表,其中包含一个链接它们的外键。年份数据在标题记录中!我希望能够查询跨年连接的所有表。

我设置了遵循“SELECT + UNION ALL”格式的视图。我还在标题表上设置了检查约束,以将它们的值限制在各自的年份。这允许 SQL Server 查询优化器在运行受 WHERE 子句限制的查询时仅查询特定表。惊人的。到目前为止,通过搜索分区视图,可以随时随地找到此信息。

我想对详细信息表进行相同类型的查询优化,但无法弄清楚。明细记录中没有任何内容表明它属于哪一年,而不与表头记录连接;意思是,外键约束是我必须摆脱的唯一约束。

我想到的唯一解决方案是在明细表中添加一个“年份”列,然后在查询中添加另一个 where 子句。我可以做些什么来使用现有的外键约束创建详细表的分区视图?


以下是一些 DDL 供参考:

CREATE TABLE header2008 (
    hid INT PRIMARY KEY,
    dt DATE CHECK ('2008-01-01' <= dt AND dt < '2009-01-01')
)

CREATE TABLE header2009 (
    hid INT PRIMARY KEY,
    dt DATE CHECK ('2009-01-01' <= dt AND dt < '2010-01-01')
)

CREATE TABLE detail2008 (
    did INT PRIMARY KEY,
    hid INT FOREIGN KEY REFERENCES header2008(hid),
    value INT
)

CREATE TABLE detail2009 (
    did INT PRIMARY KEY,
    hid INT FOREIGN KEY REFERENCES header2009(hid),
    value INT
)

GO
CREATE VIEW headerAll AS
SELECT * FROM header2008 UNION ALL
SELECT * FROM header2009
GO

CREATE VIEW detailAll AS
SELECT * FROM detail2008 UNION ALL
SELECT * FROM detail2009
GO

--This only hits the header2008 table (GOOD)
SELECT * 
FROM headerAll h
WHERE dt = '2008-04-04'

--This hits the header2008, detail2008, and detail 2009 tables. (BAD)
SELECT * 
FROM headerAll h
INNER JOIN detailAll d ON h.hid = d.hid
WHERE dt = '2008-04-04'
4

1 回答 1

0

由于您不打算使用分区表,因此我假设您不能针对 2005+ Enterprise Edition 或更高版本。

这是向表中添加新物理列的替代方法:

CREATE VIEW detailAll AS
    SELECT 2008 AS Year, * FROM detail2008
    UNION ALL
    SELECT 2009, * FROM detail2009

然后,

SELECT * 
    FROM headerAll h
    INNER JOIN detailAll d ON h.hid = d.hid
    WHERE dt = '2008-04-04' AND d.Year = 2008

在您执行此操作之前,有一个问题;好吧,实际上有两个问题。

这个解决方案,就像headerAll它所写的视图一样,不能容纳分区列上的参数并且仍然进行分区消除。使用搜索谓词的原因表扫描两个WHERE dt = @date AND d.Year = YEAR(@date)视图中的所有表,因为查询优化器假定是一个任意值(并且没有办法解决这个问题)。如果视图在数据库 API 中公开公开,这将导致性能灾难:查询中的参数化没有限制,并且大多数查询作者和 ORM 倾向于尽可能使用参数化查询(这几乎总是一件好事!) .@date

要让视图在实际应用程序中进行分区消除,您将不得不求助于动态字符串执行。如何完成这将取决于您的业务需求、数据需求和应用程序架构。如果您要获取多年的数据,这将有点棘手。

另请注意,使用动态字符串执行将允许您直接针对基表UNION编写查询,而不是为每个“表”引入ed 视图。我认为后者没有任何问题,但这是您可能没有考虑过的选项。

于 2011-07-03T05:02:50.647 回答