web-dev-qa-db-ja.com

計算列のスカラーUDFが並列処理を妨げないようにする方法はありますか?

SQL Serverの スカラーUDFの危険 については、多くのことが書かれています。さりげなく検索すると、大量の結果が返されます。

ただし、スカラーUDFが唯一のオプションである場所がいくつかあります。

例:XMLを処理する場合:XQueryは計算列の定義として使用できません。 Microsoftによって文書化されている1つのオプションは、 Scalar UDF を使用してXQueryをスカラーUDFにカプセル化し、それを計算列で使用することです。

これにはさまざまな影響があり、いくつかの回避策があります。

  • テーブルがクエリされたときに行ごとに実行します
  • テーブルに対するすべてのクエリを強制的に順次実行します

関数をスキーマバインドし、計算列を永続化するか、インデックスを作成することで、行ごとの実行を回避できます。これらのメソッドはどちらも、スカラーUDFが参照されていない場合でも、テーブルにヒットするクエリの強制的なシリアル化を防止できません。

それを行う既知の方法はありますか?

29
Erik Darling

はい次の場合:

  • sQL Server 2014以降を実行している。そして
  • トレースフラグ176アクティブでクエリを実行できます。そして
  • 計算された列はPERSISTEDです

具体的には、少なくとも次のバージョン が必要です

  • SQL Server 2016 SP1の累積的な更新2
  • SQL Server 2016 RTMの累積的な更新4
  • SQL Server 2014 SP2用の累積的な更新6

[〜#〜] but [〜#〜]バグを回避するには( 2014 の参照、および 2016および2017 )これらの修正で導入され、代わりに適用されます:

トレースフラグは、_–T_を使用するグローバルスコープとセッションスコープの両方で、およびOPTION (QUERYTRACEON)またはプランガイドを使用したクエリごとに、スタートアップ_DBCC TRACEON_オプションとして有効です。

トレースフラグ176は、計算列の拡張が保持されないようにします。

クエリのコンパイル時に実行される初期メタデータの読み込みは、直接参照されたものだけでなく、すべての列を取り込みます。これにより、すべての計算された列の定義を照合に使用できるようになります。これは一般的に良いことです。

不幸な副作用として、ロードされた(計算された)列の1つがスカラーのユーザー定義関数を使用する場合、その存在disables parallelismクエリ全体に対してeven when the計算列は実際には使用されませんです。

トレースフラグ176は、列が永続化されている場合、定義を読み込まないことでこれを支援します(展開がスキップされるため)。この方法では、スカラーユーザー定義関数はコンパイルクエリツリーに存在しないため、並列処理は無効になりません。

トレースフラグ176の主な欠点(簡単に文書化されていることを除けば)は、クエリ式が永続的な計算列に一致することも防ぐことです:クエリに永続的な計算列に一致する式が含まれている場合、トレースフラグ176によって式が置き換えられなくなります計算された列への参照。

詳細については、SQLPerformance.comの記事「 適切に永続化された計算列 」を参照してください。

質問はXMLについて言及しているので、計算列とスカラー関数を使用して値を昇格する代わりに、 Selective XML Indexes:Not Bad Atすべて

31
Paul White 9

@Paulの優れた Yes#1 に加えて、実際にはYes#2があります。

  • sQL Server 2005までさかのぼります。
  • トレースフラグを設定する必要はありません。
  • 計算列がPERSISTEDである必要があるではない、および
  • (トレースフラグ176を必要としないため)、しない永続的な計算列へのクエリ式の一致を防ぎます

(私の知る限り)唯一の欠点は次のとおりです。

  • azure SQL Databaseでは機能しません(Amazon RDS SQL ServerおよびLinux上のSQL Serverでは機能しますが、少なくともまだ機能していません)。
  • 多くのDBAの快適ゾーンの少し外側です

このオプションは次のとおりです。[〜#〜] sqlclr [〜#〜]

そのとおり。 SQLCLRスカラーUDFの優れた点の1つは、ifそれらがanyデータアクセスを行わない(ユーザーでもシステムでもない)場合、並列処理を禁止していません。そしてそれは理論やマーケティングだけではありません。私は(現時点では)完全な詳細を書く時間はありませんが、これをテストして証明しました。

私は次のブログ投稿の初期設定を使用しました(うまくいけば、O.P。はこれが信頼できないソースであるとは考えていません????):

悪いアイデアジーンズ:複数のインデックスのヒント

そして、次のテストを実行しました:

  1. 最初のクエリをそのまま実行しました─⇾並列処理(予想どおり)
  2. _([c2] * [c3])_として定義された非永続計算列を追加しました─⇾並列処理(期待どおり)
  3. その計算列を削除し、RETURN (@First * @Second);として定義されたT_SQLスカラーUDF(SCHEMABINDINGで作成)を参照する非永続計算列を追加しました。
  4. T-SQL UDF計算列を削除し、SQLCLRスカラーUDF(_IsDeterministic = true_と_= false_の両方で試してみました)をreturn SqlInt32.Multiply(First, Second);として定義されている非永続計算列を追加しました─_- Parallelism(woo hoo !!)

したがって、SQLCLRがすべての人に役立つわけではありませんが、適切な人/状況/環境にとって確かにその利点があります。そして、この特定の質問(XQueryの使用に関して与えられた例)に関連しているため、それはそのための特定の作業になります(そして、具体的に何が行われているかによっては、少し速いかもしれません????)。

10
Solomon Rutzky