web-dev-qa-db-ja.com

すべてのデータベースに対してクエリストアを有効にする

Erin Stellato の推奨設定でQuery Storeの使用を開始したいと思います。

USE [master]
GO
ALTER DATABASE DatabaseName SET QUERY_STORE = ON
GO
ALTER DATABASE DatabaseName SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO)
GO

しかし、それはデータベースごとの設定であり、インスタンスのすべてのデータベースで一度にアクティブ化できるようにしたいと考えています。

set RECOVERY Model using sp_msforeachdb(at serverfault)

OPのソリューションを使用できます

EXECUTE master.sys.sp_MSforeachdb 'USE [?];
IF DB_ID() >= 5
ALTER DATABASE [?] SET QUERY_STORE = ON
ALTER DATABASE [?] SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO)
'

動作している間、エラーが発生します

メッセージ12438、レベル16、状態1、行41

システムデータベースマスターでクエリストアを有効にできないため、アクションを実行できません。

メッセージ5069、レベル16、状態1、行41

ALTER DATABASEステートメントが失敗しました。

メッセージ12438、レベル16、状態1、行41

システムデータベースtempdbでクエリストアを有効にできないため、アクションを実行できません。

メッセージ5069、レベル16、状態1、行41

ALTER DATABASEステートメントが失敗しました。

Jason Cumberland によるソリューションのいくつかのバリエーションを試しましたが、機能しませんでした。

set quoted_identifier on

EXECUTE master.sys.sp_MSforeachdb '
IF '?' not in ('tempdb','master','model')
begin
    exec (ALTER DATABASE [?] SET QUERY_STORE = ON
ALTER DATABASE [?] SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO))
end
'

エラーが出ます

メッセージ102、レベル15、状態1、行25

「?」付近の構文が正しくありません。

これら二つは働く

  --Turn off on all databases
  EXECUTE master.sys.sp_MSforeachdb 'USE [?]; ALTER DATABASE [?] SET QUERY_STORE = OFF'

そして

--Check all Query Store database settings at once
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; SELECT * FROM sys.database_query_store_options'

質問:エラーメッセージを表示せずにインスタンスのすべてのデータベースでクエリストアを有効にするにはどうすればよいですか?

注:システムデータベースのmsdbは、クエリストアを許可する唯一のデータベースです。現在は除外していません。

SQL 2016(SP1)を実行しているSQLインスタンスに対してSSMS 17.4を使用しています

4
James Jenkins

質問で試行されたクエリのどちらの場合も、問題は単に構文上のものです。

最初のケース:IF条件がありますが、その後のステートメントをグループ化しないでください。そのため、IFの直後のステートメントのみが条件付きです。 2番目の_ALTER DATABASE_ステートメントは常に実行されます。修正するには、次のようにします。

_EXECUTE master.sys.sp_MSforeachdb N'USE [?];
IF DB_ID() >= 5
BEGIN
  ALTER DATABASE [?] SET QUERY_STORE = ON;
  ALTER DATABASE [?] SET QUERY_STORE
   (OPERATION_MODE = READ_WRITE,
    INTERVAL_LENGTH_MINUTES = 30,
    MAX_STORAGE_SIZE_MB = 1000,
    QUERY_CAPTURE_MODE = AUTO);
END;
';
_

また、おそらくUSEステートメントも必要ありません。削除してから、DB_ID()DB_ID(N''?'')に変更できます。

2番目のケース:埋め込まれた単一引用符をエスケープしませんでした。また、無関係なEXECがあり、msdbシステムデータベースが含まれていませんでした。これらすべてを修正するには、次の手順を実行します。

_EXECUTE master.sys.sp_MSforeachdb N'
IF (N''?'' NOT IN (N''tempdb'', N''master'', N''model'', N''msdb''))
BEGIN
   ALTER DATABASE [?] SET QUERY_STORE = ON;
   ALTER DATABASE [?] SET QUERY_STORE
    (OPERATION_MODE = READ_WRITE,
     INTERVAL_LENGTH_MINUTES = 30,
     MAX_STORAGE_SIZE_MB = 1000,
     QUERY_CAPTURE_MODE = AUTO);
END;
';
_

注: @Krisは、「_sp_MSForeachDB_は文書化されておらず、サポートされていない」と言っても不正確ではありません。別のメカニズムを使用してDBを循環することをお勧めします。これが1回限りのタスクであれば問題はありませんが、このコードを繰り返し使用する場合は、その警告に注意する必要があります。

5
Solomon Rutzky

最初、 sp_MSForeachDBはドキュメント化もサポートもされていないため、使用を中止してください。実際に、実際のシナリオでDBが完全に欠落しているのを見てきました。

Aaron Bertrand DBを見逃さないはるかに優れたバージョンがあります 、私は問題なくかなり長い間使用してきました。

DB内をカーソルで移動したくない場合は、古き良きダイナミックSQLを常に使用してスクリプトを生成し、手動で実行することができます。

    SELECT 'ALTER DATABASE '
    +QUOTENAME(name)+ 
    ' SET QUERY_STORE = ON;' 
FROM sys.databases  where database_id>4
3