3

特定のアプリケーションでSQL ServerのVARCHARとNVARCHARのプロと矛盾を調べると、SQL ServerがUTF8をネイティブにサポートしていると理想的です。いくつかのSOポストは例えば、そうでないことを示している:UTF-8サポート、SQL Server 2012およびUTF8String UDT

Is VARCHAR like totally 1990s?

What are the main performance differences between varchar and nvarchar SQL Server data types?

しかし、私はUTF8Stringをユーザー定義を作成する方法を示しているSQL Server 2012のために、MSDNのドキュメントで、この記事に出くわしましたデータの種類:

http://msdn.microsoft.com/en-us/library/ff877964(v=sql.110).aspx

ありながらUDTは、8ビットあたりの文字のスペース(メモリ、ディスク)の利益を可能にするようですUTF-8で表現できる文字列を格納するのに十分な柔軟性。あれは正しいですか?この戦略には欠点がありますか(例:各行の管理コードを実行するためのパフォーマンスコスト...)?

答えて

2

SQLCLRを使用してカスタムユーザー定義型を作成すると、ではなく、であり、どのようなネイティブ型も置き換えることができます。特殊なデータを処理するためのものを作成するのは非常に便利です。しかし、文字列は、異なるエンコーディングであっても、特殊化されていません。あなたの文字列データのこのルートを行くと、組み込みの文字列関数を使用することができないため、パフォーマンスはもちろんのこと、システムの使い勝手が損なわれます。

ディスク領域に何かを保存することができた場合、そのパフォーマンスは全体的なパフォーマンスを損なうことによって消去されます。 UDTの格納は、VARBINARYにシリアル化して行います。ですから文字列比較ORソートを行うには、 "バイナリ"/"順序"比較の外に、他のすべての値を1つずつUTF-8に変換してから比較する必要があります言語的な違いを説明することができます。その変換はUDT内で行う必要があります。これは、XMLデータ型と同様に、特定の値を保持するためにUDTを作成し、そのUDTのメソッドを公開して比較を行う文字列パラメータを受け入れることを意味します(つまり、Utf8String.Compare(alias.field1)Utf8string1 = Utf8string2とし、=演算子にUTF-8エンコーディングで文字列を取得してからCompareInfo.Compare()を実行します)。

上記の考察に加えて、あなたも(これを混同しないでくださいそれぞれNVARCHAR(1 - 4000)VARBINARY(1 - 4000)とは対照的に、NVARCHAR(MAX)VARBINARY(MAX)のいずれかを使用する場合は特に、SQLCLR APIを介して前後に値を渡すとコストを持っていることを考慮する必要があります使用についての何かを示唆するものとしての区別として、SqlChars/SqlBytesSqlString/SqlBinary

最後に(少なくともUDTを使用するという点で)、質問されているUDTがのサンプルコードであるという事実を見てください。注目されている唯一のテストは純粋に機能的なもので、スケーラビリティや「これを1年使った後に学んだ教訓」はまったくありません。機能テストコードは、次のCodePlexページに表示されています。この決定に進む前に、対話するためにクエリを記述する必要があるという感覚を示しています(フィールドまたは2、ほとんど/すべての文字列フィールドのない):

http://msftengprodsamples.codeplex.com/SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/Scripts/Test.sql

永続計算カラムとインデックスの数が追加さを考えると、実際に保存されたスペースでしたか? ;-)


スペース(ディスク、メモリなど)が懸念される場合は、次の3つのオプションがあります:あなたは、SQL Server 2008またはそれ以降を使用している場合

  1. を、およびEnterprise EditionでありますData Compressionを有効にすることができます。データ圧縮は、NCHARNVARCHARフィールドのUnicodeデータを圧縮できますが(「常に」はありません)。決定要因は以下のとおりです。

    1. NCHAR(1 - 4000)NVARCHAR(1 - 4000)だけのSQL Server 2008 R2で始まり、唯一のIN ROWデータではなく、OVERFLOWため、Standard Compression Scheme for Unicodeを使用します!これは、通常のROW/PAGE圧縮アルゴリズムよりも優れているようです。わからない(
    2. NVARCHAR(MAX)XML(LOBまたはオーバーフローページではありませんオフ行)行にあるデータ(と私はまたVARBINARY(MAX)TEXT、およびNTEXTを推測する)は、少なくともPAGEを圧縮することができ、かつは多分も圧縮された行この最後のものについて)。
    3. すべてのオフラインデータ、LOBまたはOVERLOW = No Compression For You! 1 VARCHARと1 NVARCHAR
  2. 2008より古いかどうかのEnterprise Editionのバージョンを使用している場合

  3. は、次の2つのフィールドを持つことができます。たとえば、ほとんどすべての基本ASCII文字(0〜127の値)を持つURLを格納していて、 VARCHARに収まるが、Unicode文字を含むことがあるとします。 [URL]計算列からこのモデルあなた だけ SELECTで

    ... 
        URLa VARCHAR(2048) NULL, 
        URLu NVARCHAR(2048) NULL, 
        URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])), 
        CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
            ([URLa] IS NOT NULL OR [URLu] IS NOT NULL) 
           AND ([URLa] IS NULL OR [URLu] IS NULL)) 
    ); 
    

    :あなたのスキーマは、次の3つのフィールドを含めることができます。あなただけの今までに収まる文字を持たなければならないフィールドを持っている場合は

    INSERT INTO TableName (..., URLa, URLu) 
    VALUES (..., 
         IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL), 
         IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL) 
         ); 
    
  4. :挿入と更新のために、あなたは変更にNVARCHARタイプである必要があり、着信値を、変換した場合見ることによって、使用するフィールドを決定します拡張ASCII文字セットの特定のコードページは、VARCHARを使用してください。


P.S.ただ、これは明確にするために述べました:SQL Serverの2012年に導入された新しい_SC照合順序は、単にを可能に:

  • 適切に補助文字/サロゲートペアを処理するために、組み込み関数、および
  • 言語的ルール補足順序付けのために使用されている文字と比較しても新しい_SC照合順序なし

しかし、のために、あなたはまだXMLまたはN -prefixed型に任意のUnicode文字を格納することができ、およびデータ損失なしでそれを取得します。ただし、古いCollat​​ions(名前にバージョン番号がない)を使用すると、すべての補足文字が互いに一致します。 _90_100の照合を使用する必要があります。少なくとも、バイナリ/コードポイントの比較とソートが必要です。補足文字の特定のマッピングを持たない(したがって重みや正規化ルールを持たない)ため、言語ルールを考慮することはできません。

は、以下のことを試してください:DBで

IF (N'' = N'') SELECT N'' AS [TheLiteral], NCHAR(150150) AS [Generated]; 
IF (N'' = N'') SELECT N'' AS [TheLiteral], NCHAR(150151) AS [Generated]; 
IF (N'' COLLATE Tatar_90_CI_AI = N'' COLLATE Tatar_90_CI_AI) 
     SELECT N' COLLATE Tatar_90_CI_AI' AS [TheLiteral], NCHAR(150151) AS [Generated]; 
IF (N'' = N'?') SELECT N'?'; 

_SCで終わる既定の照合順序を持つ、唯一の最初のIFの文は、結果セットを返し、「生成」フィールドが正しく文字が表示されます。

しかし、DBは_SCで終わるデフォルトの照合を持っていない、との照合が_90または_100シリーズの照合でない場合は、「生成」フィールドはNULLを返します。ここでは、最初の2つのIF文は、結果セットを返します「リテラル」フィールドが正しく表示されます。

Unicodeデータの場合、照合順序は物理ストレージに影響しません。

+0

「NVARCHAR(1 - 4000)」とは何ですか? –

+0

@EricJ。 1から4000までの数値を指定することを意味します。 –

+0

@EricJ。申し訳ありませんが、私はそれについて明確ではなかった。基本的にAaronは言っています:それは、1 - 4000の範囲内にしかない非 'MAX' NVARCHAR型を示す私の方法です。 –

関連する問題