utf8_general_ci と utf8_unicode_ci の違いは何ですか
-
12-09-2019 - |
質問
間 utf8_general_ci
そして utf8_unicode_ci
, 、性能面で違いはあるのでしょうか?
解決
これら 2 つの照合順序は両方とも UTF-8 文字エンコーディング用です。違いは、テキストの並べ替えと比較の方法にあります。
注記:MySQL 5.5.3 以降は使用する必要があります utf8mb4
それよりも utf8
. 。どちらも UTF-8 エンコーディングを指しますが、古いものは utf8
MySQL 固有の制限により、0xFFFD より大きい番号の文字の使用が禁止されていました。
主な違い
utf8mb4_unicode_ci
は、ユニバーサルな並べ替えと比較のための公式 Unicode ルールに基づいており、幅広い言語で正確に並べ替えられます。utf8mb4_general_ci
は、速度を向上させるために設計された多くのショートカットを使用しながら、できる限りうまく実行することを目的とした、簡略化された並べ替えルールのセットです。これは Unicode ルールに従っていないため、特定の言語や文字を使用する場合など、状況によっては望ましくない並べ替えや比較が行われます。最新のサーバーでは、このパフォーマンスの向上はほとんど無視できます。これは、サーバーの CPU パフォーマンスが今日のコンピューターのほんの一部にすぎなかった時代に考案されました。
注記:現在、の更新バージョンが存在します utf8mb4_unicode_ci
呼ばれた utf8mb4_0900_ai_ci
- これは Unicode バージョン 9.0 の変更に基づいており、明らかに高速です。新しい命名スキームを採用しています。 0900
は Unicode バージョンであり、 ai
前と同じように、アクセントを区別しないことを意味します utf8mb4_unicode_ci
, 、文字のアクセントは重要とはみなされません。
のメリット utf8mb4_unicode_ci
以上 utf8mb4_general_ci
utf8mb4_unicode_ci
, は、並べ替えと比較に Unicode ルールを使用し、さまざまな言語で、またさまざまな特殊文字を使用する場合に正しく並べ替えるために、かなり複雑なアルゴリズムを採用しています。これらのルールでは、言語固有の規則を考慮する必要があります。誰もがいわゆる「アルファベット順」に文字を並べ替えているわけではありません。
ラテン語 (つまり「ヨーロッパ」) 言語に関する限り、Unicode ソートと簡略化されたソートの間に大きな違いはありません。 utf8mb4_general_ci
MySQL でのソートですが、まだいくつかの違いがあります。
たとえば、Unicode 照合順序では、「ß」は「ss」のように、「ā」は「OE」のように、これらの文字を使用するユーザーが通常望むようにソートされます。
utf8mb4_general_ci
それらを単一の文字としてソートします (おそらくそれぞれ "s" と "e" のように)。一部の Unicode 文字は無視できるものとして定義されています。つまり、それらの文字は並べ替え順序にカウントされず、代わりに比較が次の文字に進む必要があります。
utf8mb4_unicode_ci
これらを適切に処理します。
アジア言語や異なるアルファベットの言語など、ラテン語以外の言語では、 もっと Unicode ソートと簡略化されたソートの違い utf8mb4_general_ci
並べ替え。の適合性 utf8mb4_general_ci
使用される言語に大きく依存します。一部の言語では、これではまったく不十分です。
何を使えばいいのでしょうか?
ほぼ確実に使用する理由がありません utf8mb4_general_ci
CPU 速度が十分に低いため、パフォーマンスの違いが重要になるという点はもう取り残されています。データベースはほぼ確実に、これ以外のボトルネックによって制限されます。
過去に使用を推奨した人もいました utf8mb4_general_ci
ただし、正確な並べ替えがパフォーマンス コストを正当化するのに十分なほど重要である場合は除きます。現在、そのパフォーマンスコストはほとんどなくなり、開発者は国際化をより真剣に扱うようになりました。
正確さよりも速度が重要な場合は、並べ替えをまったく行わないほうがよいという議論もあります。アルゴリズムを正確にする必要がない場合、アルゴリズムを高速化するのは簡単です。それで、 utf8mb4_general_ci
これはおそらく速度上の理由から必要ではなく、精度の理由からもおそらく適切ではない妥協です。
もう 1 つ付け加えておきたいのは、アプリケーションが英語のみをサポートしていることがわかっている場合でも、人名を処理する必要がある場合があります。人名には他の言語で使用される文字が含まれていることが多く、正しく並べ替えることも同様に重要です。 。すべてに Unicode ルールを使用すると、非常に賢い Unicode 担当者が並べ替えを適切に機能させるために一生懸命働いているという安心感が得られます。
部品の意味
まず、 ci
のためのものです 大文字小文字を区別しません 並べ替えと比較。これは、テキスト データに適しており、大文字と小文字は重要ではないことを意味します。他の種類の照合順序は次のとおりです。 cs
(大文字と小文字を区別) 大文字と小文字が重要なテキスト データの場合、 bin
, 、エンコードがビットごとに一致する必要がある場合、実際にエンコードされたバイナリ データ (Base64 など) であるフィールドに適しています。大文字と小文字を区別した並べ替えは奇妙な結果をもたらし、大文字と小文字を区別した比較では大文字と小文字のみが異なる重複値が生じる可能性があるため、テキスト データでは大文字と小文字を区別した照合順序は好まれなくなりつつあります。大文字と小文字が重要である場合、そうでない場合は句読点は無視できます。などもおそらく重要であり、バイナリ照合の方が適切である可能性があります。
次、 unicode
または general
特定の並べ替えと比較のルール、特にテキストを正規化または比較する方法を指します。utf8mb4 文字エンコーディングにはさまざまなルールのセットがあり、 unicode
そして general
この 2 つは、特定の 1 つの言語ではなく、すべての可能な言語で適切に動作するように努めています。これら 2 つのルール セットの違いがこの回答の主題です。新しいルール セットには次のものが含まれることに注意してください。 0900
Unicode 9.0 を参照し、 unicode_520
Unicode 5.2を参照します。
そして最後に、 utf8mb4
もちろん内部で使用される文字エンコーディングです。この回答では、Unicode ベースのエンコーディングについてのみ説明します。
他のヒント
を使用した場合のパフォーマンスの違いを知りたかった utf8_general_ci
そして utf8_unicode_ci
, しかし、ネット上にベンチマークが載っていなかったので、自分でベンチマークを作成することにしました。
500,000 行の非常に単純なテーブルを作成しました。
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
次に、次のストアド プロシージャを実行して、ランダム データを入力しました。
CREATE PROCEDURE randomizer()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE random CHAR(20) ;
theloop: loop
SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
INSERT INTO test VALUES (i+1, random);
SET i=i+1;
IF i = 500000 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END
次に、単純なベンチマークを行うために次のストアド プロシージャを作成しました。 SELECT
, SELECT
と LIKE
, 、および並べ替え (SELECT
と ORDER BY
):
CREATE PROCEDURE benchmark_simple_select()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description = 'test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_select_like()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description LIKE '%test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_order_by()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
SET i = i + 1;
IF i = 10 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
上記のストアド プロシージャでは utf8_general_ci
照合順序が使用されますが、もちろんテスト中は両方を使用しました utf8_general_ci
そして utf8_unicode_ci
.
各照合順序ごとに各ストアド プロシージャを 5 回呼び出しました ( utf8_general_ci
そして5回 utf8_unicode_ci
) を計算し、平均値を計算しました。
私の結果は次のとおりです。
benchmark_simple_select()
- と
utf8_general_ci
:9,957ミリ秒 - と
utf8_unicode_ci
:10,271ミリ秒
このベンチマークでは、 utf8_unicode_ci
よりも遅いです utf8_general_ci
3.2%増加しました。
benchmark_select_like()
- と
utf8_general_ci
:11,441ミリ秒 - と
utf8_unicode_ci
:12,811ミリ秒
このベンチマークでは、 utf8_unicode_ci
よりも遅いです utf8_general_ci
12%増加しました。
benchmark_order_by()
- と
utf8_general_ci
:11,944ミリ秒 - と
utf8_unicode_ci
:12,887ミリ秒
このベンチマークでは、 utf8_unicode_ci
よりも遅いです utf8_general_ci
7.9%増加しました。
この投稿には非常にうまくそれを説明しています。
要するに:ユニコード規格で定義されているようutf8_general_ci「はあまり正確」ソート結果をもたらす、より単純なソート順であるのに対しutf8_unicode_ci内には、Unicode照合アルゴリズムを使用する
。/ <のUnicode文字セット、MySQLのマニュアルを参照してください>セクションます:
任意のUnicode文字セットの場合、 操作は、使用して行います _general_ci照合_unicode_ci照合のためのものより高速です。 例えば、比較 utf8_general_ciの照合高速化され、 しかし、わずかに少ない正しい、より utf8_unicode_ci内のための比較。ザ・ この理由は、ということです utf8_unicode_ci内には、このようなマッピングをサポートしています 拡張として、それは、ときです 文字はに関し平等の比較します 他の文字の組み合わせ。ために ドイツや他のいくつかの例では、 言語「ß」は「SS」に等しいです。 utf8_unicode_ci内でもサポートしています 収縮と無視できる文字。 utf8_general_ciは、従来の照合であります それは、拡張をサポートしていません。 収縮、または無視できる文字。 それだけで1対1を作ることができます 文字間の比較ます。
そこでの全体の標準を実装する必要がutf_general_ciにをutf_unicode_ciより比較の小さいと(標準に従って)以下の正しいセットを使用して、要約します。行うには以下の計算があるのでgeneral_ciセットが速くなります。
の の
あなたがより良い順番を並べ替える必要がある場合 - 使用utf8_unicode_ci
(これは好ましい方法である)、
が、パフォーマンスで、あなたは全く興味があれば - utf8_general_ci
を使用しますが、それは少し古くなっていることを知っています。
パフォーマンスの面での違いはごくわずかです。
いくつかの詳細 (PL)
読んでわかるように ここ (ピーター・グルツァン) ポーランド語文字「Ł」 (L とストローク - html Esc:) の並べ替え/比較に違いがあります。 Ł
) (小文字:"ł" - HTML ESC: ł
) - 次の仮定があります。
utf8_polish_ci Ł greater than L and less than M
utf8_unicode_ci Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci Ł greater than Z
ポーランド語の手紙 Ł
手紙の後です L
そしてその前に M
. 。このコーディングのどれが良いか悪いということはありません。それはニーズによって異なります。