web-dev-qa-db-ja.com

SQL Server 2017でSNAPSHOT_MATERIALIZATIONを使用してビューを作成するにはどうすればよいですか?

SQL Server 2017には、いくつかの新しいストアドプロシージャがあります。

  • sp_refresh_single_snapshot_view – @view_name nvarchar(261)の入力パラメーター、@ rgCode int
  • sp_refresh_snapshot_views – @rgCode intの入力パラメーター

そして、sys.messagesの新しいエントリ:

  • 10149 –ビュー定義にメモリ最適化テーブルが含まれているため、SNAPSHOT_MATERIALIZATIONを持つインデックスをビュー ‘%。* ls’に作成できません。
  • 10642-SNAPSHOT_MATERIALIZATIONはビューのインデックスにのみ適用できるため、 ‘%。* ls’のインデックス ‘%。* ls’に設定できません。
  • 10643 – SNAPSHOT_MATERIALIZATIONは、ビューのクラスター化インデックスにのみ適用できるため、 ‘%。* ls’の ‘%。* ls’に設定できません。
  • 10648 – SNAPSHOT_MATERIALIZATIONは、 ‘%。* ls’のパーティションインデックス ‘%。* ls’には設定できません。
  • 10649 –非クラスター化インデックス ‘%。* ls’は、SNAPSHOT_MATERIALIZATIONでクラスター化インデックス ‘%。* ls’を持つ ‘%。* ls’に作成できません。
  • 10650 –スナップショットビューを更新するには、データベースでスナップショット分離を有効にする必要があります。
  • 3760 – SNAPSHOT_MATERIALIZATIONを持つビュー ‘%。* ls’のインデックス ‘%。* ls’は削除できません。
  • 4524 –ビュー ‘%。* ls’はスナップショットマテリアライズがあるため変更できません。
  • 4525 –ビューが更新される前にスナップショットマテリアライズされたビュー ‘%。* ls’でヒント ‘%ls’を使用できません。

そして、新しい拡張イベント:

Snapshot view Extended Events

それでは、どのようにしてスナップショットマテリアライズドビューを作成できますか? (Microsoftはまだそれを文書化していません。)これが これまでに試したものの要点 機能していません。

36
Brent Ozar

できません。この機能は2017 RTMでは無効になっています。


つまり、次のことができます...

AdventureWorksの使用:

CREATE VIEW dbo.TH
WITH SCHEMABINDING
AS
SELECT P.ProductID, COUNT_BIG(*) AS cbs
FROM Production.Product AS P
JOIN Production.TransactionHistory AS TH
    ON TH.ProductID = P.ProductID
GROUP BY P.ProductID;
GO
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.TH (ProductID)
WITH (SNAPSHOT_MATERIALIZATION = ON);

基になるテーブルへの変更は、ビューにすぐには反映されません(SQL Serverの場合は通常そうです)。同様に、基になるテーブルに対するデータ変更は、スナップショットインデックス付きビューを維持する必要はありません。

ビューの内容を更新するには、新しいストアドプロシージャの1つを呼び出す必要があります。

EXECUTE sys.sp_refresh_single_snapshot_view
    @view_name = N'dbo.TH',
    @rgCode = 0; -- don't know what this is for yet

これにより、実行計画が作成されます。

Plan

文書化されていないトレースフラグが必要であるか、特に厄介なことを行う必要があるため、これは機能しない可能性があります。この機能を有効にするには、(デバッガーを使用して)機能フラグを保持するメモリ位置に書き込みます。

興味があれば、機能フラグはsqllang!g_featureSwitchesLangSvc+0x10fのバイトです。 sqllang!SpRefreshSingleSnapshotViewの間にチェックされます。

一緒に遊んで、SQL Serverのコードを実行中にハッキングして、Microsoftがまだ準備ができていないと思われる機能を使用した結果を受け入れる準備が整っている場合:

  1. SQL Server 2017プロセスにデバッガーを接続します。 WinDbgを使用しています。
  2. ブレークポイントを設定します。

    bp sqllang!SpRefreshSingleSnapshotView
    
  3. Goコマンドを使用してSQL Serverを再開する(g

  4. 上記のビューを作成しますが、一意のクラスター化インデックスはまだ作成していません
  5. 上記のsys.sp_refresh_single_snapshot_viewコマンドを実行します
  6. ブレークポイントに到達したら、コード行が表示されるまでステップ実行します。

    cmp byte ptr [sqllang!g_featureSwitchesLangSvc+0x10f (00007fff`328dfbcf)],0
    

    オフセットは他のビルドでは異なる場合があります。たとえば、2017 RTM CU3ではsqllang!g_featureSwitchesLangSvc+0x114

  7. 括弧内のメモリアドレスは異なる場合があります。表示されているものを使用してください。

  8. Display memoryコマンドを使用して、見つかったメモリアドレスの現在の値を確認します。

    db 00007fff`328dfbcf L1
    
  9. これはゼロを示し、機能が無効であることを示します。

  10. Enter値コマンドを使用して(ここでもメモリアドレスを使用して)、ゼロを1に変更します。

    eb 00007fff`328dfbcf 1
    
  11. ブレークポイントを無効にして、SQL Serverの実行を再開します。

  12. これで機能が有効になります。
  13. ビューに一意のクラスター化インデックスを作成します。
  14. 遊んでみてください。

SNAPSHOT_MATERIALIZATIONを使用すると、通常はインデックスを作成できなかったクエリ仕様のスナップショットを具体化できます。たとえば、以下ではMAXを使用しています。

CREATE VIEW dbo.TH2
WITH SCHEMABINDING
AS
SELECT TH.ProductID, MaxTransactionID = MAX(TH.TransactionID)
FROM Production.TransactionHistory AS TH
GROUP BY TH.ProductID;
GO
CREATE UNIQUE CLUSTERED INDEX cuq ON dbo.TH2 (ProductID)
WITH (SNAPSHOT_MATERIALIZATION = ON);

結果:

コマンドは正常に完了しました。
56
Paul White 9