これは、Max Vernonの回避策を改善する試みです。彼のソリューションでは、ビューで2つのインデックスと統計オブジェクトを使用することを提案しています。
最初のインデックスはクラスター化されます。これは、テーブル上の非クラスター化インデックスとは異なり、最初にクラスター化インデックスがなくてもビューで非クラスター化インデックスを作成しようとするとエラーが生成されるため、実際に必要です。
2番目のインデックスは、クエリの背後にあるインデックスとして使用される非クラスター化インデックスです。彼の回答のコメントセクションで、非クラスター化インデックスの代わりにクラスター化インデックスを使用するとどうなるかを尋ねました。
次の分析では、この質問に答えようとします。
ビューに非クラスター化インデックスを作成していないことを除いて、彼とまったく同じコードを使用しています。
統計オブジェクトも作成していません。従い、SQL Server Management Studio(SSMS)を使用して以下のコードを入力する場合、エラーのように見える赤い波線が表示される場合があることに注意してください。これらは(おそらく)エラーではありませんが、インテリセンスに問題があります。
インテリセンスを無効にするか、エラーを無視してコマンドを実行することができます。エラーなしで完了します。
-- Create the test table that uses a computed column.
USE tempdb;
CREATE TABLE dbo.PersistedViewTest
(
PersistedViewTest_ID INT NOT NULL
CONSTRAINT PK_PersistedViewTest
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, SomeData VARCHAR(2000) NOT NULL
, TestComputedColumn AS (PersistedViewTest_ID - 1) PERSISTED
);
GO
-- Insert some test data into the table.
INSERT INTO dbo.PersistedViewTest (SomeData)
SELECT o.name + o1.name + o2.name
FROM sys.objects o
CROSS JOIN sys.objects o1
CROSS JOIN sys.objects o2;
GO
次のクエリがテーブルに対して実行された後、次の実行プラン(ビュー/インデックスビューなし)が作成されます。
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
これにより、比較するベースラインが得られます。クエリが完了した後、統計オブジェクトが作成されたことに注意してください(_WA_Sys_00000003_1FCDBCEB)。PK_PersistedViewTest統計オブジェクトは、クラスター化テーブルインデックスの作成時に作成されました。
次に、フィルタービューとそのビューのクラスター化インデックスが作成されます。
-- Create filtered view on the computed column.
CREATE VIEW dbo.PersistedViewTest_View
WITH SCHEMABINDING
AS
SELECT PersistedViewTest_ID, SomeData, TestComputedColumn
FROM dbo.PersistedViewTest
WHERE TestComputedColumn < CONVERT(INT, 27);
GO
-- Create unique clustered index to persist the values, including the computed column.
CREATE UNIQUE CLUSTERED INDEX IX_PersistedViewTest
ON dbo.PersistedViewTest_View(PersistedViewTest_ID);
GO
ここで、クエリを再度実行してみましょう。ただし、今回はビューに対して:
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
新しい実行計画は次のとおりです。
新しいプランが考えられる場合、そのビューにビューとクラスター化インデックスを追加すると、クエリの実行に必要な時間が倍になったことを示す統計が表示されます。また、クエリの実行後に新しいインデックスをサポートするための新しい統計オブジェクトが作成されていないことに注意してください。これは、テーブルのクエリとは異なります。
クエリプランでは、非クラスター化インデックスの作成がクエリのパフォーマンスの向上に非常に役立つことを引き続き示しています。それでは、目的のパフォーマンスの向上を得るには、ビューに非クラスター化インデックスを追加する必要があるということですか?最後に試してみてください。「WITH NOEXPAND」オプションを使用するようにクエリを変更します。
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv WITH (NOEXPAND)
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
これにより、次のクエリプランが作成されます。
この実行計画は、Max Vernonの回答で指定された非クラスター化インデックスを使用して作成されたものと非常によく似ています。ただし、これは、1つ少ない(非クラスター化)インデックスと1つ少ない統計オブジェクトで行われます。
インデックス付きビューを適切に使用するには、SQL Serverの高速バージョンと標準バージョンでNOEXPANDオプションを使用する必要があることがわかります。Paul Whiteには、NOEXPANDオプションを使用する利点について詳しく説明した優れた記事があります。また、ビューインデックスによって提供される一意性保証がオプティマイザーによって使用されるように、このオプションをエンタープライズエディションで使用することをお勧めします。
上記の分析は、SQL Sever 2014のエクスプレス版で行われました。SQLServer 2016の開発者版でも試してみました。NOEXPANDオプションは、パフォーマンスの向上を達成するために開発版では必要ないようですが、それでも推奨されます。
5か月未満前に、Microsoftは開発者向けエディションを無料にしました。このライセンスでは、使用が開発のみに制限されています。つまり、本番環境ではデータベースを使用できません。したがって、メモリに最適化されたテーブル、暗号化、Rなどをテストする場合は、ライセンスなしの言い訳はできなくなります。数日前に問題なくSQL Server 2014 Expressと共にコンピューターに正常にインストールしました。
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
ただし、フィルター処理されたインデックスを作成できます。