C#コードで実装されたCLRスカラーUDFを持っています。入力パラメーターにString
データ型を使用すると、SqlString
データ型に比べてパフォーマンスが大幅に向上することに気付きました。 SQLCLRレベル5への階段:開発(SQL Server内での.NETの使用) では、 Solomon Rutzky は、文字列にSQLデータ型を好む次の理由について述べています。
ネイティブ共通言語ランタイム(CLR)データ型とSQL Serverデータ型の主な違いは、前者はNULL値を許可しないが、後者は完全なNULLセマンティクスを提供することです。
...
のストリーミング値は、N [VAR] CHARの場合はSqlChars、[VAR] BINARYの場合はSqlBytes、XMLの場合はSqlXml.CreateReader()を使用して実現できます。
...
SqlString(文字列やSqlCharsではない)を使用する場合、CompareInfo、CultureInfo、LCID、およびSqlCompareOptionsプロパティにアクセスできます...
入力がNULLになることはなく、値をストリームインする必要もありません。また、照合プロパティをチェックすることもありません。私の場合は、String
の代わりにSqlString
を使用するほうがよい例外でしょうか?そのやり方をすれば、特に気をつけるべきことはありますか?
問題がある場合は、SQL Serverの既定の照合順序を使用しています。これは私のソースコードの一部であり、s1
は入力パラメーターです。
fixed (char* chptr = s1)
{
char* cp = (char*)current;
for (int i = 0; i < s1.Length; i++)
{
cp[i] = chptr[i];
}
}
すばらしい質問です。私の知る限り、これらの条件(つまり、NULL
sがなく、追加の機能が必要ないことが保証されている)のもとでは、特に心配する必要はありません。これはCURSOR
sに似た状況であり、一般的なルールが必要な場合は、「カーソルを使用しない」です。ただし、実際のルールは、「適切なときに/場所でのみカーソルを使用する」です。問題は、カーソルの技術的な詳細について人々に教育して、彼らが決定を下せるようにすることです。そのようなことについて十分に知っている私たちは、一般的なルールを無視し、適切に使用します。
したがって、混乱とエラーを減らすため、「常に」_Sql*
_型を使用することをお勧めします。しかし、それはあなたの状況でstring
を使用するのが良くないということではありません。私はそれのために行くと言い、string
で問題が発生した場合は、戻ってSqlString
に変更するのは簡単です。
照合とあなたの声明に関して:
問題がある場合は、SQL Serverの既定の照合順序を使用しています。
これは一般に問題ではありませんが、真のデフォルト照合がないことを考えると、ここで何を意味するかも少し不明確です。言語設定が「US English」のOSにSQL Serverをインストールするときに、 不運なデフォルト照合を参照している可能性があります (つまり、LCID = 1033)、つまり_SQL_Latin1_General_CP1_CI_AS
_。ただし、すべて異なる3つのレベルの照合順序(インスタンス/サーバー、データベース、および列)がまだあり、これらのレベルの1つまたは2つだけを意味している場合があります。
私がこれすべてについて言及する理由は、いくつかの非自明なことがここで起こっているということです:
sQLCLRスレッドの既定のカルチャはOSレベルの言語設定(選択した言語のLCID)であるため、照合が影響するこれらの3つのレベルはある程度関係ありません。これは、2つの_String.Equals
_値のいずれかを使用する場合は_StringComparison.CurrentCulture*
_を使用する操作に影響し、カルチャを指定しない場合は_String.Compare
_を使用する操作に影響します。
_=
_演算子は序数比較を行うため(つまり、__BIN2
_照合順序を使用する場合と同じである必要があるため)、照合順序が影響を与えるこれら3つのレベルはある程度関係ありません。これは_String.CompareOrdinal
_の動作方法でもあります。notが_String.Equals
_または_StringComparison.CurrentCulture*
_の値を渡す場合の_StringComparison.InvariantCulture*
_も同様です。
sQL Server照合が重要な1つの例は、SqlString
入力パラメーターを_+
_を介してstring
と連結する場合です。この場合、_+
_演算子は、SqlString
の値を含む新しいstring
を作成して、2つのSqlStrings
を連結できるようにします。問題は、新しいSqlString
が現在のスレッドLCID(オペレーティングシステムのLCID)で作成され、次に_+
_演算子が連結の前に2つのSqlStrings
を比較することです(つまり、それらが「同じタイプ」であることを確認します。ただし、SqlString
入力パラメーターにdatabase(インスタンスまたは列ではない)のLCIDがあり、暗黙的に作成されたSqlString
があるため、 OSのLCIDの場合、操作は「照合順序」が一致しないことを示す例外を受け取ります。いいですね
ただし、文字列が必要なときにSqlString
の値を直接使用する必要はないため、これはshouldの問題ではありません。代わりに、全員が常にValue
プロパティを使用して文字列を取得する必要があります。
とはいえ、string
の方が高速であると判断するためにどのようなテストを行ったかについて知りたいと思います。単一のNVARCHAR(4000)
入力パラメーターを受け入れ、短い文字列を連結してから新しい値を返す単純なUDFをテストしました。そのUDFの1つのバージョンはstring
を受け入れて返し、もう1つのバージョンはSqlString
を受け入れて返します。 100万回を超えるstring
バージョンはSqlString
バージョンよりも約200〜300ミリ秒高速であり、最速の時間(100万回の繰り返しではなく、それぞれ)。残りの50%の時間では、パフォーマンスの向上は約100ミリ秒でしたが、まったくない場合もあります。
また、テストコードに関しては、string
であろうとSqlString
であろうと、_s1
_は常に直接入力パラメーターですか?はいの場合、ローカルで文字列を作成し、それを_s1.Value
_に設定することもテストする必要があります。意味:
_string s2 = s1.Value; // when s1 is SqlString instead of string
fixed (char* chptr = s2)
{
char* cp = (char*)current;
for (int i = 0; i < s2.Length; i++)
{
cp[i] = chptr[i];
}
}
_
また、おそらくテストする他のいくつかのオプション:
byte[]
_を返します)char[]
_を返します)