私のOpenCart
テーブル照合順序はutf8_bin
ですが、残念ながら、名前にアクセントが付いている製品名を検索することはできません。 Googleで検索したところ、アクセント互換で大文字と小文字を区別しない検索を行うには、照合順序をutf8_general_ci
にする必要があることがわかりました。
検索クエリに照合宣言を追加するとどうなりますか?
SELECT *
FROM `address`
COLLATE utf8_general_ci
LIMIT 0 , 30
(悪い)副作用はありますか?インデックス作成、パフォーマンスの問題について赤字ですか?それとも完全に安全ですか?
クエリのパフォーマンスへの副作用、特にインデックスを使用する場合の副作用を考慮する必要があります。簡単なテストは次のとおりです。
mysql> create table aaa (a1 varchar(100) collate latin1_general_ci, tot int);
insert into aaa values('test1',3) , ('test2',4), ('test5',5);
mysql> create index aindex on aaa (a1);
Query OK, 0 rows affected (0.59 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc aaa;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| a1 | varchar(100) | YES | MUL | NULL | |
| tot | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.53 sec)
mysql> explain select * from aaa where a1='test1' ;
+----+-------------+-------+------+---------------+--------+---------+-------+--
----+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | r
ows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+--
----+-----------------------+
| 1 | SIMPLE | aaa | ref | aindex | aindex | 103 | const |
1 | Using index condition |
+----+-------------+-------+------+---------------+--------+---------+-------+--
----+-----------------------+
1 row in set (0.13 sec)
mysql> explain select * from aaa where a1='test1' collate utf8_general_ci;
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows
| Extra |
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-------------+
| 1 | SIMPLE | aaa | ALL | NULL | NULL | NULL | NULL | 3
| Using where |
+----+-------------+-------+------+---------------+------+---------+------+-----
-+-------------+
1 row in set (0.06 sec)
別の照合を使用して検索すると、MySQLがa1のインデックスの使用を停止していることがわかります。これは、大きな問題になる可能性があります。
インデックスがクエリに使用されていることを確認するには、列の照合順序を最も頻繁に使用される照合順序に変更する必要がある場合があります。
SQLステートメントでのCOLLATEの使用 では、その使用法は見つかりません。とにかく、照合を使用した場合の影響に関する主な質問について説明するために、いくつかのヒントを見つけましたが、最初は次のとおりです。
dev.mysql.comから:
非バイナリ文字列(
CHAR
、VARCHAR
、およびTEXT
データ型に格納されている)には、文字セットと照合順序があります。特定の文字セットには複数の照合順序を設定できます。各照合順序は、セット内の文字の特定の並べ替えおよび比較順序を定義します。
複数のオペランドがあると、あいまいさが生じる可能性があります。例えば:
_SELECT x FROM T WHERE x = 'Y';
_
比較では、列x
の照合、または文字列リテラル_'Y'
_の照合を使用する必要がありますか? x
と_'Y'
_の両方に照合順序があるので、どちらの照合順序が優先されますか?
標準SQLは、以前は「強制力」ルールと呼ばれていたものを使用してこのような質問を解決します。 [3]
ORDER BY
_- [WHERE
]-でもINDEX
を使用できなくなります。したがって、驚くほど非効率的である可能性があります。 [4]utf8_general_ci
_はほぼ確実に_utf8_bin
_追加のルックアップ/計算が必要なため)。これは役立つかもしれません: TF-8:General?Bin?Unicode?utf8_bin
も大文字と小文字を区別することに注意してください。そのため、テーブルの照合順序をutf8_general_ci
に変更して、将来に備えて安心します。
可能であれば、列の定義を変更してください。
_ALTER TABLE tbl
MODIFY col VARCHAR(...) COLLATE utf8_general_ci ...;
_
(列定義にすでに含まれている他のものをすべて含める必要があります。)変更する列が複数ある場合は、すべて同じALTERで実行します(速度を上げるため)。
何らかの理由でALTER
を実行できない場合は、はい、SELECT
を微調整して照合順序を変更できます。
あなたが言及したSELECT
にはフィルタリング用のWHERE
句がなかったので、テストケースを変更しましょう。
これがあるとしましょう。これは「サンノゼ」のみを検索します。
_SELECT *
FROM tbl
WHERE city = 'San Jose'
_
_San José
_を含めるには:
_SELECT *
FROM tbl
WHERE city COLLATE utf8_general_ci = 'San Jose'
_
「アクセントの組み合わせ」がある場合は、utf8_unicode_ciの使用を検討してください。 発音区別符号の組み合わせの詳細 および トピックの詳細 。
副作用は?潜在的に大きいものを除いてなし:列のインデックスは使用できません。私の2番目のSELECT
(上記)では、INDEX(city)
は役に立たない。 ALTER
は、SELECT
に対するこのパフォーマンスの低下を回避しますが、1回限りのALTER
自体はコストがかかります。