25

私は MSSQL Server 2008 R2 を使用しており、インデックス付きビューに出くわしたときにビューを最適化しようとしています。残念ながら、私のビューのほとんどは、インデックス付きビューではサポートされていない左外部結合を使用しています。たくさんの調査の後、私はこれを行うための最良の方法を混乱させました。私の見方では、次のオプションがあります。

1)「OR (IsNull(a) AND IsNull(b))」で左結合をシミュレートするトリックを使用して、左結合を内部結合に変換します。

この解決策はいくつかの場所で見つかりましたが、パフォーマンスの低下について言及されていました。

2)左結合を内部結合に変換し、null 許容列の null を空の GUID (00000000-0000-0000-0000-000000000000) に置き換え、一致する GUID を持つ単一の行を右側のテーブルに追加します。

これはパフォーマンスに関して最も明白なように見えますが、それ以外の場合は NULL になるすべての行のスペースの無駄のようです。

3)ビューを 2 つのビューに分割します。最初のビューは、Indexable である私のロジックの大部分です。そして、最初のビューから派生し、左結合を追加する 2 番目のビュー。

ここでのアイデアは、インデックス化されたベース ビューによってパフォーマンスが向上する可能性があることです。また、派生ビューにクエリを実行しても、少なくともパフォーマンス上のメリットがいくらか得られます。

4)ビューにインデックスを付けない

ビューをそのままにしておくと、上記のどのオプションよりもパフォーマンスが向上しますか?

5)思いつかなかったアイデア

基本的なシナリオを次のようにスクリプト化しました。

   CREATE TABLE [dbo].[tbl_Thumbnails](
        [ThumbnailId] [uniqueidentifier] NOT NULL,
        [Data] [image] NULL,
        [Width] [smallint] NOT NULL,
        [Height] [smallint] NOT NULL
     CONSTRAINT [PK_tbl_Thumbnails] PRIMARY KEY CLUSTERED 
    (
        [ThumbnailId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    GO

    CREATE TABLE [dbo].[tbl_Tags](
        [TagId] [uniqueidentifier] NOT NULL,
        [ThumbnailId] [uniqueidentifier] NULL
     CONSTRAINT [PK_tbl_Tags] PRIMARY KEY CLUSTERED 
    (
        [TagId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    CREATE VIEW [dbo].[v_Tags] WITH SCHEMABINDING AS
    SELECT     dbo.tbl_Tags.TagId, dbo.tbl_Tags.ThumbnailId
    FROM         dbo.tbl_Tags LEFT OUTER JOIN
                          dbo.tbl_Thumbnails
    ON     dbo.tbl_Tags.ThumbnailId = dbo.tbl_Thumbnails.ThumbnailId

    GO

    INSERT INTO tbl_Tags VALUES ('16b23bb8-bf17-4784-b80a-220da1163584', NULL)
    INSERT INTO tbl_Tags VALUES ('e8b50f03-65a9-4d1e-b3b4-268f01645c4e', 'a45e357b-ca9c-449a-aa27-834614eb3f6e')
    INSERT INTO tbl_Thumbnails VALUES ('a45e357b-ca9c-449a-aa27-834614eb3f6e', NULL, 150, 150)

ここで、次のクエリを実行すると、「ビュー "Test.dbo.v_Tags" にインデックスを作成できません。これは、LEFT、RIGHT、または FULL OUTER 結合を使用しており、インデックス付きビューでは OUTER 結合が許可されていないためです。代わりに、INNER 結合の使用を検討してください。 ":

CREATE UNIQUE CLUSTERED INDEX [TagId] ON [dbo].[v_Tags] 
(
[TagId] ASC
)
GO 

これは予想される動作ですが、私のシナリオから最高のパフォーマンスを得るには、どのような行動をお勧めしますか? ここでの持ち帰りポイントは最高のパフォーマンスです。

4

1 に答える 1

6

なぜビューをインデックス化するのですか? ソリューション 2 で「スペースの浪費」について言及しましたが、ビューにインデックスを付けると、DB に永続化されることをご存知ですか?

つまり、ビューが DB に返すデータのコピーを作成し、ソース テーブルでデータが更新されるたびに、SQL Server の内部メカニズムの一部が、作成されたこの新しいデータ構造でデータを更新する必要があります。テーブルからではなく、ビューから読み取ります。

Profiler + DTAまたはDMVSを使用すると、どのビューからも恩恵を受けるテーブルに作成される正しいインデックスを見つけることができます

于 2012-04-06T14:32:30.613 に答える