1

私はドキュメントを読んだり、よくある質問を見たりしてきましたが、これに対する答えが見つかりませんでした。おそらく、それはできないことを意味します. 私の実際の状況はもう少し複雑ですが、この質問のために単純化しようとします. 過去の各年について、それらをリンクする外部キーを持つヘッダー/詳細テーブルがあります。年データはヘッダー レコードにあります。何年にもわたって連結されたすべてのテーブルを照会できるようにしたいと考えています。

「SELECT + UNION ALL」形式に従うビューを設定しました。また、ヘッダー テーブルにチェック制約を設定して、値をそれぞれの年に制限しました。これにより、SQL サーバー クエリ オプティマイザーは、WHERE 句で制限されたクエリを実行するときに、特定のテーブルのみをクエリできます。素晴らしい。この時点まで、この情報は、Partitioned Views を検索することでどこでも見つけることができます。

詳細テーブルで同じようなクエリの最適化を行いたいのですが、わかりません。詳細レコードには、ヘッダー レコードと結合しない限り、それが何年に属しているかを示すものは何もありません。つまり、外部キー制約は、私が外さなければならない唯一の制約です。

私が考えた唯一の解決策は、詳細テーブルに「年」列を追加してから、別の 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

これを実行して実装する前に、落とし穴があります。まあ、実際には2回のキャッチです。

このソリューションは、headerAll書かれているビューと同様に、パーティション列のパラメーターに対応できず、パーティションの削除を行います。原因テーブルの検索述語を使用すると、両方のWHERE dt = @date AND d.Year = YEAR(@date)ビューのすべてのテーブルがスキャンされます。これは、クエリ オプティマイザーがを任意の値と見なすためです (それを修正する方法はありません)。これは、ビューがデータベース API で公開されている場合、パフォーマンスが低下する原因となります: クエリのパラメーター化に制限はなく、ほとんどのクエリ作成者と ORM は可能な限りパラメーター化されたクエリを使用する傾向があります (ほとんどの場合、これは良いことです!) .@date

ビューが実際のアプリケーションでパーティションの削除を行うようにするには、動的な文字列の実行に頼る必要があります。これをどのように達成するかは、ビジネス要件、データ要件、およびアプリケーション アーキテクチャによって異なります。複数年のデータを取得する場合は、少し複雑になります。

また、動的文字列実行を使用すると、 「テーブル」ごとに ed ビューを導入する代わりに、ベース テーブルに対して直接クエリを記述できることにも注意してください。UNION後者に問題があるとは思いませんが、これはあなたが考慮していない可能性のあるオプションです。

于 2011-07-03T05:02:50.647 に答える