との間utf8_general_ci
でutf8_unicode_ci
、パフォーマンスの点で違いはありますか?
utf8[mb4]_unicode_ci
、あなたはあり好きutf8[mb4]_unicode_520_ci
もっと。
utf8mb4_0900_ai_ci
です。
との間utf8_general_ci
でutf8_unicode_ci
、パフォーマンスの点で違いはありますか?
utf8[mb4]_unicode_ci
、あなたはあり好きutf8[mb4]_unicode_520_ci
もっと。
utf8mb4_0900_ai_ci
です。
回答:
これら2つの照合順序は、どちらもUTF-8文字エンコーディング用です。違いは、テキストのソート方法と比較方法です。
注:MySQL utf8mb4
では、ではなくを使用する必要がありますutf8
。紛らわしいことに、utf8
これは下位互換性のためにのみ残されている初期のMySQLバージョンからの欠陥のあるUTF-8実装です。修正バージョンには名前が付けられましたutf8mb4
。
注:MySQLの新しいバージョンでは utf8mb4_0900_ai_ci
、Unicode 9.0に基づく同等のルール などの名前で利用可能なUnicodeの並べ替えルールが更新され、同等の_general
バリアント はありません。これを読んでいる人は、おそらく、_unicode
またはの 代わりに、これらの新しい照合順序の1つを使用する必要があります_general
。代わりに新しい照合順序の1つを使用できる場合、以下に記載されている内容の多くは、あまり関心がありません。
主な違い
utf8mb4_unicode_ci
は、幅広い言語で正確に並べ替えられるユニバーサルな並べ替えと比較のための公式のUnicodeルールに基づいています。
utf8mb4_general_ci
は、速度を向上させるために設計された多くのショートカットを実行しながら、できることと同じように実行することを目的とした並べ替えルールの簡略化されたセットです。これはUnicode規則に準拠していないため、特定の言語や文字を使用する場合など、状況によっては望ましくない並べ替えや比較が行われます。
最近のサーバーでは、このパフォーマンスの向上はほとんど無視できます。サーバーが今日のコンピュータのCPUパフォーマンスのごく一部を占めていたときに考案されました。
utf8mb4_unicode_ci
以上のメリットutf8mb4_general_ci
utf8mb4_unicode_ci
は、並べ替えと比較にUnicodeルールを使用し、さまざまな言語で、さまざまな特殊文字を使用するときに、かなり複雑なアルゴリズムを使用して正しい並べ替えを行います。これらのルールでは、言語固有の規則を考慮する必要があります。誰もが「アルファベット順」と呼ぶもので文字を並べ替えるわけではありません。
ラテン語(つまり「ヨーロッパ」)言語に関する限りutf8mb4_general_ci
、MySQLのUnicodeソートと単純化されたソートには大きな違いはありませんが、いくつかの違いがあります。
たとえば、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の人々が並べ替えを適切に機能させるために非常に一生懸命に取り組んできたので、安心が得られます。
パーツの意味
1つ目ci
は、大文字と小文字を区別しない並べ替えと比較です。これは、テキストデータに適していることを意味し、大文字と小文字は重要ではありません。他のタイプの照合はcs
、大文字と小文字が区別されるテキストデータの場合(大文字と小文字が区別されます)bin
、エンコーディングが一致する必要がある場合はビットごとに行われます。これは、実際にエンコードされたバイナリデータ(たとえば、 Base64)。大文字と小文字を区別する並べ替えは、奇妙な結果につながり、大文字と小文字を区別する比較では、大文字と小文字のみが異なる重複値が生じる可能性があるため、大文字と小文字を区別する照合は、テキストデータでは優先されません。などもおそらく重要であり、バイナリ照合がより適切な場合があります。
次に、unicode
またはgeneral
特定の並べ替えおよび比較ルールを参照します-特に、テキストが正規化または比較される方法。そこutf8mb4文字エンコーディングのための規則の多くの異なるセットをして、あるunicode
とgeneral
考えられるすべての言語ではなく、ある特定の1でうまく動作するように2つのという試みています。これらの2つのルールセットの違いは、この回答の主題です。unicode
はUnicode 4.0のルールを使用していることに注意してください。MySQLの最近のバージョンではunicode_520
、Unicode 5.2のルールを使用してルールセットを追加し、0900
(「unicode_」の部分を削除して)Unicode 9.0のルールを使用しています。
そして最後に、utf8mb4
もちろん内部的に使用される文字エンコーディングです。この回答では、Unicodeベースのエンコーディングについてのみ話しています。
utf8_general_ci
:それは単に動作しません。それは、50年前からのASCII stooopeeedityの古き良き時代の先祖返りです。Unicodeの大文字と小文字を区別しない一致は、UCDからの折りたたみマップなしでは実行できません。たとえば、「Σίσυφος」には3つの異なるシグマがあります。または、「TSCHüẞ」の小文字は「tschüβ」ですが、「tschüβ」の大文字は「TSCHÜSS」です。あなたは正しいことができる、またはあなたは速いことができます。したがって、を使用する必要がありますutf8_unicode_ci
。正確さを気にしない場合は、無限に高速にするのは簡単です。
"か" == "が"
か"ǽ" == "æ"
。ソートにはこれは理にかなっていますが、等式を使用して選択したり、一意のインデックスを処理したりすると驚くかもしれません-bugs.mysql.com/bug.php?id=16526
utf8mb4
が唯一の正しい選択です。ではutf8
、あなただけのMySQL(およびMariaDB)というUTF8のいくつかのMySQLのみ、3バイトの変種で立ち往生していると何をすべきか知っています。その他の国ではUTF8を使用しており、1文字あたり最大4バイトを含めることができます。MySQL開発者は、自作のエンコーディングの名前を誤ってutf8
おり、下位互換性を壊さないように、実際のUTF8をとして参照する必要がありますutf8mb4
。
私が使用して性能差が何であるかを知りたいと思った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
次に、次のストアドプロシージャを作成して、simple SELECT
、SELECT
with LIKE
、sorting(SELECT
with 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回ずつ照合するための各ストアドプロシージャ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
使用するには価値がありません。
CONV(FLOOR(RAND() * 99999999999999), 20, 36)
つまり、ASCIIのみを生成し、照合のアルゴリズムで処理されるUnicode文字は生成しません。2)Description = 'test' COLLATE ...
とDescription LIKE 'test%' COLLATE ...
、実行時にのみ単一の文字列(「テスト」)を処理し、しない彼らは?3)実際のアプリでは、順序付けに使用される列にはおそらくインデックスが付けられ、実際の非ASCIIテキストとの異なる照合でのインデックス作成速度は異なる場合があります。
この投稿はそれを非常にうまく説明しています。
つまり、utf8_unicode_ciは、Unicode標準で定義されているUnicode照合アルゴリズムを使用しますが、utf8_general_ciは、より単純な並べ替え順序であり、結果として「精度が低く」なります。
utf8_unicode_ci
して、もう一方が存在しないふりをするだけです。
utf8_general_ci
なるなら、あなたのためかもしれません
mysqlマニュアルの「Unicode Character Sets」セクションを参照してください。
Unicode文字セットの場合、_general_ci照合を使用して実行される操作は、_unicode_ci照合の操作よりも高速です。たとえば、utf8_general_ci照合の比較は、utf8_unicode_ciの比較より高速ですが、少し正確ではありません。これは、utf8_unicode_ciが展開などのマッピングをサポートしているためです。つまり、1つの文字が他の文字の組み合わせと等しい場合。たとえば、ドイツ語およびその他のいくつかの言語では、「ß」は「ss」と同じです。utf8_unicode_ciは、縮約と無視できる文字もサポートしています。utf8_general_ciは、拡張、縮小、または無視できる文字をサポートしないレガシー照合です。文字間の比較は1対1しかできません。
要約すると、utf_general_ciは、標準全体を実装するutf_unicode_ciよりも(標準に従って)小さくて正確性の低い比較セットを使用します。実行する計算が少ないため、general_ciセットはより高速になります。
utf8_unicode_ci
バグのある壊れたバージョンが存在しないふりをするだけです。
0
との間の実数1
であり、boolではありません。:) EGがバウンディングボックスでジオポイントを選択することは、「近くのポイント」の近似であり、ポイントと参照ポイントの間の距離を計算し、それをフィルタリングすることほど良くありません。しかし、どちらも概算であり、実際には、完全な正確さはほとんど達成できません。海岸線のパラドックスとIEEE 754を
1/3
簡単に言えば:
より良い並べ替え順序が必要な場合-使用 utf8_unicode_ci
(これが推奨される方法です)、
ただし、パフォーマンスに完全に関心がある場合は、 utf8_general_ci
しますが、少し古いことを知っています。
パフォーマンスの違いはごくわずかです。
ここで読むことができるように(Peter Gulutzan)ポーランド語の文字 "Ł"(L with stroke-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
です。このコーディングのどれも良くも悪くもありません-それはあなたのニーズに依存します。
並べ替えと文字一致には2つの大きな違いがあります。
並べ替え:
utf8mb4_general_ci
すべてのアクセントを削除し、1つずつ並べ替えます。これにより、正しくない並べ替え結果が作成される可能性があります。utf8mb4_unicode_ci
正確に並べ替えます。文字マッチング
キャラクターのマッチングは異なります。
たとえば、utf8mb4_unicode_ci
あなたはを持っていますがi != ı
、utf8mb4_general_ci
それを保持していますı=i
。
たとえば、の行があるとしname="Yılmaz"
ます。その後
select id from users where name='Yilmaz';
コロケーションがの場合は行を返しますがutf8mb4_general_ci
、コロケーションされてutf8mb4_unicode_ci
いる場合は行を返しません。
一方、それはありますがa=ª
、ß=ss
にutf8mb4_unicode_ci
は当てはまりませんutf8mb4_general_ci
。でname="ªßi"
、次の行があるとします。
select id from users where name='assi';
コロケーションがの場合は行を返しますがutf8mb4_unicode_ci
、コロケーションがに設定されている場合は行を返しませんutf8mb4_general_ci
。
utf8mb4_unicode_ciの代わりにutf8mb4_general_ciを使用している場合、この記事によると、MySQLの5.7の非常に大きなパフォーマンス上の利点があります: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact -on-mysql-performance /