私がアクセスされる一部の非決定的関数参照しているビューに出くわしたデータベースプロファイリングしながら、毎分1000から2500回をするために、各このアプリケーションのプール内の接続を。SELECT
ビューからの単純な結果は、次の実行計画をもたらします。
これは、数か月ごとに1行または2行の変更が発生する可能性がある1000行未満のビューの複雑な計画のようです。しかし、次のその他の遵守事項により悪化します。
- ネストされたビューは非決定的であるため、インデックスを作成できません
- 各ビューは複数
UDF
のを参照して文字列を作成します - 各UDFには
UDF
、ローカライズされた言語のISOコードを取得するためのネストされたsが含まれています - スタック内のビューは、s から返された追加の文字列ビルダーを述語として使用しています
UDF
JOIN
- 各ビュースタックはテーブルとして扱われます。つまり、基礎となるテーブルに書き込むためにそれぞれに
INSERT
/UPDATE
/DELETE
トリガーがあります。 - ビューのこれらのトリガーは、これらの文字列構築をより多く参照
CURSORS
するEXEC
ストアドプロシージャを使用しますUDF
。
これはかなり腐っているように見えますが、TSQLの経験は数年しかありません。それも良くなります!
これは素晴らしいアイデアだと判断した開発者UDF
は、スキーマ固有の文字列から返された文字列に基づいて、格納されている数百の文字列を翻訳できるように、すべてを実行したようです。
スタック内のビューの1つを次に示しますが、それらはすべて等しく劣っています。
CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
, CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.I18NString
ELSE il.I18nString
END AS WKString
,CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.IETFLangCode
ELSE il.IETFLangCode
END AS IETFLangCode
,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode
,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON (
il.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON (
id.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO
UDF
sがJOIN
述語として使用されている理由は次のとおりです。I18NID
カラムを連結することによって形成されます。STRING + [ + ID + | + ID + ]
これらのテスト中SELECT
、ビューからの単純なものは〜309行を返し、実行に900-1400msかかります。文字列を別のテーブルにダンプし、インデックスをスラップすると、同じ選択が20〜75ミリ秒で返されます。
だから、長い話を短く(そしてこの愚かさのいくらかを感謝してほしい)私は良いサマリア人になり、ローカライズをまったく使用しないこの製品を実行しているクライアントの99%のためにこれを再設計し、書き直したい- - [en-US]
英語が第2/3言語である場合でも、エンドユーザーはロケールを使用する必要があります。
これは非公式のハックなので、次のことを考えています。
- 元の基本テーブルからのデータのきれいに結合されたセットで移入された新しい文字列テーブルを作成します
- テーブルにインデックスを付けます。
- 含まスタックの最上位レベルのビューの置換セットの作成
NVARCHAR
とINT
の列WKType
とWKIndex
列を。 UDF
これらのビューを参照する少数のsを変更して、一部の結合述部での型変換を回避します(最大の監査テーブルは500〜2,000M行INT
で、NVARCHAR(4000)
列に対する結合に使用される列に格納しWKIndex
ます(INT
))。- ビューをスキーマバインドする
- ビューにいくつかのインデックスを追加します
- カーソルの代わりに設定ロジックを使用して、ビューでトリガーを再構築します
さて、私の実際の質問:
- ビューを介してローカライズされた文字列を処理するためのベストプラクティスの方法はありますか?
- を
UDF
スタブとして使用するための選択肢はどれですか?(VIEW
さまざまなUDF
スタブに依存する代わりに、スキーマの所有者ごとに固有のものを記述し、言語をハードコーディングできます。) - これらのビューは、ネストされた
UDF
sを完全に修飾してからビュースタックをスキーマバインドすることで、単純に決定論的にできますか?
UDF
定義も投稿してください。また、参照してくださいT-SQLユーザー定義関数:良い、悪い、と醜い