UTF-8:一般?置き場?Unicode?


279

さまざまな種類のデータに使用する必要がある照合順序を把握しようとしています。保存するコンテンツの100%はユーザーが送信します。

私の理解では、UTF-8バイナリの代わりにUTF-8 General CI(大文字と小文字を区別しない)を使用する必要があります。ただし、UTF-8 General CIとUTF-8 Unicode CIの明確な区別が見つかりません。

  1. ユーザーが送信したコンテンツをUTF-8 GeneralまたはUTF-8 Unicode CI列に保存する必要がありますか?
  2. UTF-8 Binaryはどのタイプのデータに適用できますか?

16
余談ですが、の代わりにutf8utf8mb4完全なUTF-8サポートに代わりに使用してください。この人気のある質問に対する回答はこれに対処していないため、ここでコメントします。mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis

大文字と小文字を区別したいがアクセントの区別が必要な場合は、bugs.mysql.comでリクエストを送信してください
リックジェームズ

または、bugs.mysql.com / bug.php?id = 58797の [ Affects Me]をクリックしてコメントを追加します。
リックジェームズ

回答:


299

一般的には、utf8_general_ciは速くよりutf8_unicode_ci内、あまり正しいです。

ここに違いがあります:

Unicode文字セットの場合、_general_ci照合を使用して実行される操作は、_unicode_ci照合の操作よりも高速です。たとえば、utf8_general_ci照合の比較は、utf8_unicode_ciの比較よりも高速ですが、少し正確ではありません。これは、utf8_unicode_ciが展開などのマッピングをサポートしているためです。つまり、1つの文字が他の文字の組み合わせと等しい場合。たとえば、ドイツ語およびその他のいくつかの言語では、「ß」は「ss」と同じです。utf8_unicode_ciは、縮約と無視できる文字もサポートしています。utf8_general_ciは、拡張、縮小、または無視できる文字をサポートしないレガシー照合です。文字間の比較は1対1しかできません。

引用元:http : //dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

詳細については、MySQLフォーラムの次の投稿をご覧ください。http: //forums.mysql.com/read.php?103,187048,188748

utf8_binの場合:utf8_general_ciutf8_unicode_ciはどちらも大文字と小文字を区別しない比較を実行します。対照的に、utf8_binは文字のバイナリ値を比較するため、(他の違いの中でも)大文字と小文字が区別されます。


2
_unicode_ciを使用する十分な理由がない場合は、_general_ciを使用してください。
サギ

4
しかし、これは実際には質問の答えにはなりません。これらの照合の正確な違いは何ですか?
ペッカ

4
あなたが正しい、正確さの違いはここでは単純化のために提供されていません。正確な違いのあるリンクを投稿に追加しました。
Sagi

NB show collation;では、各文字セットのデフォルトの照合を確認できます。5.1はのutf8_general_ciデフォルトとして表示されますutf8
David Carboni

9
2つの照合順序の間の実際の速度の違いをさらに詳しく説明するリソースはありますか?パフォーマンスの低下は0.1%ですか、それとも10%ですか。
Emphram Stavanger 2013

90

また、utf8_general_ciを使用して、varcharフィールドを一意のインデックスまたはプライマリインデックスとして使用し、「a」や「á」などの2つの値を挿入すると、重複キーエラーが発生することにも注意してください。


3
おかげで、これは同様のユーザー名を回避するのに役立ちます(たとえば、「jose」が存在する場合、他の誰かが「josé」ユーザーを作成することは望ましくありません)。最も確実/最も安全/最も包括的なのはutf8_unicode_ci
Costa

2
インデックスでホセとホセを区別したい場合は、utf8_binを使用します。たとえば、ユーザーがjoséを検索してjoseに置き換えることを決定した可能性がある検索/置換操作を記録する列。(私はスプレッドシートプログラムを書いています)
Buttle Butkus 2013年

33
  • utf8_binビットを盲目的に比較します。ケースの折りたたみ、アクセントの剥ぎ取りはありません。
  • utf8_general_ci1バイトと1バイトを比較します。大文字小文字の折りたたみアクセントの除去は行いますが、2文字の比較ijは行われませんij。この照合では等しくありません。
  • utf8_*_ciは言語固有のルールのセットですが、それ以外はのようになりunicode_ciます。いくつかの特殊な例:ÇČchll
  • utf8_unicode_ci比較のために古いUnicode標準に従います。ij= ij、しかしae!=æ
  • utf8_unicode_520_ci新しいUnicode標準に従います。 ae=æ

参照照合チャート、各種のutf8照合順序で何に等しい内容の詳細については。

utf8MySQLが定義されるような 1〜3バイトのUTF8コードに限定されます。これにより、絵文字と一部の中国語が省略されます。したがって、utf8mb4ヨーロッパをはるかに超えて行きたい場合は、実際に切り替える必要があります。

上記の点は、 utf8mb4は、適切なスペルの変更後、に。今後、utf8mb4かつutf8mb4_unicode_520_ci好ましいです。

  • utf16とutf32はutf8のバリアントです。それらの使用は事実上ありません。
  • ucs2は「utf8」よりも「Unicode」に近いです。実質的にそれを使用する必要はありません。

1
「調整を続ける」:8.0の照合順序は、8.0 utf8mb4照合順序でさまざまな文字、複母音などがどのように比較されるかを示しています。utf8はほとんど同じです。
リックジェームズ

また、8.0照合は5.xよりも大幅に高速で処理されます
リックジェームズ

そのページの上部にutf8mb4_binがリストされていると便利です。文字マッチングはまったく行わないことはわかっていますが、初心者には適しています。
Henk Poley

6

本当に、私はとの列で「E」と「E」のような値の保存試験をユニークにインデックスをしたところ、「utf8_unicode_ci」と「utf8_general_ci」の両方で重複エラーが発生しました。「utf8_bin」の照合列にのみ保存できます。

mysqlのドキュメント(http://dev.mysql.com/doc/refman/5.7/en/charset-applications.htmlにあります)は、その例に 'utf8_general_ci'照合順序セットを示唆しています。

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

1
これについて簡単なテストを行いましたが、正確であるようです。列の一意のキーとチルダなどの値に関しては、どちらの照合も同じように動作します。
MirroredFate 2015年

@MirroredFate OK、列にこのエラーを引き起こすための一意のインデックスが必要です。それは私の答えを意味します。
vitalii 2015

3

受け入れられた回答は古くなっています。

MySQL 5.5.3以降を使用している場合は、のutf8mb4_unicode_ci代わりにutf8_unicode_ciを使用して、ユーザーが入力した文字によってエラーが発生しないことを確認してください。

utf8mb4たとえば、絵文字をサポートしutf8ますが、次のようなエンコーディング関連の何百ものバグが発生する可能性があります。

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1


この回答は、絵文字(および一部の中国語)のエンコードに関する問題に(正しく)対処しています。しかし、質問は照合に集中しているようです。 utf8mb4_unicode_ciすべての絵文字を同等に扱う(私は思う)。 utf8mb4_unicode_520_ci絵文字を注文します。
リックジェームズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.