MySQL:在查询中整理 - 任何副作用?

时间:2015-04-28 21:55:15

标签: mysql collation

我的OpenCart表格排序是utf8_bin,遗憾的是我无法搜索名称中带有重音的产品名称。我在Google上进行了搜索,发现校对必须为utf8_general_ci,以便对重音符号和不区分大小写的搜索进行搜索。

如果我在搜索查询中添加整理声明怎么办?

SELECT * 
FROM  `address` 
COLLATE utf8_general_ci
LIMIT 0 , 30

是否有任何(不良)副作用?我是关于索引,性能的问题?还是完全安全?

4 个答案:

答案 0 :(得分:3)

我担心你必须考虑查询性能的副作用,特别是那些使用索引的人。这是一个简单的测试:

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上的索引,这对你来说可能是个大问题。

要确保将索引用于查询,可能必须将列排序规则更改为最常用的列。

答案 1 :(得分:1)

using of COLLATE in SQL statements中,我找不到这种用法,无论如何,为了解释使用归类的影响的主要问题,我找到了一些提示,但首先是:

来自 dev.mysql.com

  

非二进制字符串(存储在CHARVARCHARTEXT数据类型中)具有字符集和排序规则。给定的字符集可以有多个排序规则,每个排序规则为集合中的字符定义特定排序比较顺序

  1. 排序规则只是用于字符串比较的排序 - 它(几乎)与用于数据存储的字符编码无关。我说几乎是因为排序规则只能用于某些字符集,因此更改排序规则可能会强制更改字符编码 在修改字符编码的范围内,MySQL将正确地将值重新编码为新字符集,无论是从单字节还是多字节,反之亦然。请注意,任何对列过大的值都将被截断。 [1]
  2. 二进制整理的实际优点是速度,因为字符串比较非常简单/快速。在一般情况下,带二进制的索引可能不会产生排序的预期结果,但是对于完全匹配,它们可能很有用。 [2]
  3. 对于多个操作数,可能存在歧义。例如:

    SELECT x FROM T WHERE x = 'Y';
    

    比较是否应使用列x或字符串文字'Y'的排序规则? x'Y'都有排序规则,因此整理排序优先吗? 标准SQL使用以前称为“强制性”规则的方法解决此类问题。 [3]

  4. 如果您更改字段的整理,ORDER BY - [也在WHERE]中 - 不能使用任何INDEX;因此它可能会出乎意料地效率低下。 [4]
  5. 由于强制归类是通过与列编码相同的字符集定义的,因此不会产生任何性能影响(而不是将归类定义为列的默认值;而{{由于需要额外的查找/计算,1}}在比较中几乎肯定会比utf8_general_ci执行速度慢 但是,如果强制使用不同字符集定义的排序规则,则MySQL必须对列的值进行转码(这会对性能产生影响)。 [5] < / LI>

答案 2 :(得分:0)

如果可行,请更改列定义。

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。 More on Combining DiacriticalsMore on your topic

副作用?除了可能很大的一个:无法使用列上的索引。在我的第二个SELECT(上图)中,INDEX(city)没用。 ALTER SELECT避免了ALTER的性能损失,但一次性touchesMoved本身就很昂贵。

答案 3 :(得分:0)

这可能有所帮助:UTF-8: General? Bin? Unicode? 请注意,utf8_bin也区分大小写。因此,我会将表格整理改为utf8_general_ci,并为将来安心。