web-dev-qa-db-ja.com

SQL Server 2019で「nvarchar / nchar」が使用されるのはいつですか?

SQL Server 2019で、MicrosoftはCHARおよびVARCHARデータ型に TF-8サポート を導入し、次のように述べています。

この機能により、使用中の文字セットによっては、ストレージを大幅に節約できる場合があります。たとえば、UTF-8対応の照合を使用してASCII文字列をNCHAR(10)からCHAR(10)に変更して既存の列データ型を変更すると、ストレージ要件が約50%削減されます。これは削減は、NCHAR(10)がストレージに22バイトを必要とするのに対し、CHAR(10)は同じUnicode文字列に12バイトを必要とするためです。

UTF-8は support すべてのスクリプトと思われるので、基本的にはvarchar列とchar列にUnicodeデータの格納を開始できます。ドキュメントで述べられているように、これによりテーブルとインデックスのサイズを削減でき、そこから読み取られるデータの量が少なくなるため、パフォーマンスがさらに向上します。

これは、UTF-16を実装するnvarcharおよびnchar列の使用を停止できることを意味しているのでしょうか。

誰かがシナリオと理由を指摘できますか?UTFエンコーディングでcharデータ型を使用せず、n-charsのものを引き続き使用しますか?

11
gotqn

これcanテーブルとインデックスのサイズを小さくします(強調を追加)

サイズの削減は、文字のmostが本質的に_[space]_、_0 - 9_、_A - Z_、_a - z_、およびいくつかの基本的な句読点。その特定の文字セット(実際の使用条件では、標準ASCII値32〜126)の外では、サイズはせいぜい等しくなりますNVARCHAR/UTF-16、または多くの場合それよりも大きい。

読み取るデータが少なくなるとシステムのパフォーマンスが向上するので、データの移行を計画しています。

注意してください。 UTF-8は魔法の「すべてを修正する」スイッチではありません。他のすべての条件が同じである場合は、はい、読んだ回数が少なくてもパフォーマンスは向上します。しかし、ここで「他のすべてのもの」は等しくないのみを格納する場合でも標準ASCII文字(つまり、すべての文字は1バイトであるため、NVARCHAR)、UTF-8を使用するとパフォーマンスが若干低下します。UTF-8が可変長エンコーディングであるため、問題が発生するのは、各バイトを読み取るときに解釈する必要があることを意味します。それが完全な文字である場合、または次のバイトがその一部である場合。これは、すべての文字列操作が最初から始まり、バイトごとに進む必要があることを意味します。一方、NVARCHAR/UTF -16は常に2バイト(補足文字も2バイトの2バイトコードポイントで構成されます)なので、すべてを2バイトチャンクで読み取ることができます。

私のテストでは、only標準ASCII文字でさえ、データをUTF-8として保存すると、経過時間の節約は提供されませんでしたが、明らかにより悪かったですCPU時間を節約します。データ圧縮を使用しなかったため、少なくとも使用されるディスク領域は少なくなりましたが、圧縮を使用すると、UTF-8に必要な領域は1%から1.5%しか小さくなりませんでした。 UTF-8のCPU時間。

NVARCHAR(MAX)を使用すると、値が行に格納できるほど小さい場合でも、そのデータ型ではUnicode圧縮が機能しないため、状況はさらに複雑になります。ただし、データが十分に小さい場合でも、行またはページの圧縮のメリットが得られます(この場合、実際にはUTF-8よりも高速になります)。ただし、行外データは圧縮を使用できません。それでも、テーブルをクラスター化列ストアインデックスにすると、NVARCHAR(MAX)のサイズが大幅に削減されます(クラスター化列ストアインデックスを使用するときにUTF-8より少し大きい場合でも)。

誰かがシナリオと理由を指摘できますか?UTFエンコーディングでcharデータ型を使用しないでください

絶対に。実際、ほとんどの場合、私は実際にそれを使用する説得力のある理由を見つけていません。 UTF-8から本当にメリットがある唯一のシナリオは次のとおりです。

  1. データはほとんど標準ASCII(値0-127)
  2. mightは、単一の8ビットコードページ(つまり、VARCHAR)で使用できるよりも広い範囲の文字を格納する必要があるため、Unicodeである必要があります。
  3. ほとんどのデータはオフローで保存されます(そのため、ページ圧縮は機能しません)
  4. クエリパフォーマンス以外の理由でサイズを削減する必要がある/したい十分なデータがある(バックアップサイズの削減、バックアップ/復元に必要な時間の削減など)
  5. クラスター化列ストアインデックスは使用できません(この場合、テーブルを使用するとパフォーマンスが低下する可能性があります)。

私のテストでは、ほとんどすべてのケースで、特にデータが多い場合にNVARCHARの方が高速であったことが示されています。実際、1行あたり平均5k文字の21k行には、UTF-8で165 MB、非圧縮のNVARCHARで236 MBが必要でした。それでも、NVARCHARは経過時間で2倍、CPU時間で少なくとも2倍(場合によってはそれ以上)高速でした。それでも、ディスク上でさらに71 MBを消費しました。

それ以外でも、少なくともCTP 2以降はUTF-8を使用することはお勧めしません。この機能で見つかったさまざまなバグが原因です。

UTF-16とUTF-8の違いの説明を含むこの新機能の詳細な分析、およびそれらのバグのリストについては、私の投稿を参照してください。

SQL Server 2019のネイティブUTF-8サポート:救世主か偽預言者か

6
Solomon Rutzky

UTF-8サポートにより、新しいオプションセットが提供されます。潜在的なスペース節約( 行またはページの圧縮なし なし)は1つの考慮事項ですが、タイプとエンコーディングの選択は、主に比較、ソート、データのインポートとエクスポート

あなたが思っている以上に変更する必要があるかもしれません。 nchar(1)タイプは、2バイトのストレージを提供します。 [〜#〜] bmp [〜#〜] (コードポイント000000〜00FFFF)に任意の文字を格納するには、これで十分です。その範囲の一部の文字はUTF-8で1バイトだけでエンコードされますが、その他の文字は2バイトまたは3バイトさえ必要です(詳細は この比較表 を参照)。したがって、UTF-8で同じ文字セットを確実にカバーするには、char(3)が必要です。

例えば:

_DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);
_

おなじみのエラーを出します:

メッセージ8152、レベル16、状態30、行xxx
文字列型やバイナリは省略されます。

または、トレースフラグ460がアクティブな場合:

メッセージ2628、レベル16、状態1、行xxx
文字列またはバイナリデータは、テーブル '@T'、列 'UTF8'で切り捨てられます。切り捨てられた値: ''。

UTF8列をchar(2)またはvarchar(2)に展開すると、NCHAR(911)のエラーが解決されます。

_DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);
_

ただし、たとえばNCHAR(8364)char(3)またはvarchar(3)に列をさらに展開する必要があります。

また、UTF-8照合はすべて補助文字を使用するため、レプリケーションでは 機能しません となることに注意してください。

それ以外は、UTF-8サポートは現時点ではプレビュー段階にあるため、本番環境では使用できません。

12
Paul White 9