SQL Serverの スカラーUDFの危険 については、多くのことが書かれています。さりげなく検索すると、大量の結果が返されます。
ただし、スカラーUDFが唯一のオプションである場所がいくつかあります。
例:XMLを処理する場合:XQueryは計算列の定義として使用できません。 Microsoftによって文書化されている1つのオプションは、 Scalar UDF を使用してXQueryをスカラーUDFにカプセル化し、それを計算列で使用することです。
これにはさまざまな影響があり、いくつかの回避策があります。
関数をスキーマバインドし、計算列を永続化するか、インデックスを作成することで、行ごとの実行を回避できます。これらのメソッドはどちらも、スカラーUDFが参照されていない場合でも、テーブルにヒットするクエリの強制的なシリアル化を防止できません。
それを行う既知の方法はありますか?
はい次の場合:
PERSISTED
です具体的には、少なくとも次のバージョン が必要です 。
[〜#〜] 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すべて 。
@Paulの優れた Yes#1 に加えて、実際にはYes#2があります。
PERSISTED
である必要があるではない、および(私の知る限り)唯一の欠点は次のとおりです。
このオプションは次のとおりです。[〜#〜] sqlclr [〜#〜]
そのとおり。 SQLCLRスカラーUDFの優れた点の1つは、ifそれらがanyデータアクセスを行わない(ユーザーでもシステムでもない)場合、並列処理を禁止していません。そしてそれは理論やマーケティングだけではありません。私は(現時点では)完全な詳細を書く時間はありませんが、これをテストして証明しました。
私は次のブログ投稿の初期設定を使用しました(うまくいけば、O.P。はこれが信頼できないソースであるとは考えていません????):
そして、次のテストを実行しました:
([c2] * [c3])
_として定義された非永続計算列を追加しました─⇾並列処理(期待どおり)RETURN (@First * @Second);
として定義されたT_SQLスカラーUDF(SCHEMABINDING
で作成)を参照する非永続計算列を追加しました。IsDeterministic = true
_と_= false
_の両方で試してみました)をreturn SqlInt32.Multiply(First, Second);
として定義されている非永続計算列を追加しました─_- Parallelism(woo hoo !!)したがって、SQLCLRがすべての人に役立つわけではありませんが、適切な人/状況/環境にとって確かにその利点があります。そして、この特定の質問(XQueryの使用に関して与えられた例)に関連しているため、それはそのための特定の作業になります(そして、具体的に何が行われているかによっては、少し速いかもしれません????)。