我想知道MySQL在生成索引时是否会将排序规则考虑在内,或者无论排序规则如何生成相同的索引,只有在以后遍历该索引时才会考虑排序规则。
出于我的目的,我想在字段上使用排序规则utf8_unicode_ci。我知道这种特殊的校对具有相对较高的性能损失,但使用它仍然很重要。
我在该字段上有一个索引,用于满足ORDER BY子句,快速检索行(避免使用filesort)。但是,我不确定使用此排序规则是否会影响从索引读回的行的速度,或者索引是否根据该排序规则将数据存储在已经标准化的状态,从而导致性能损失完全在生成索引而不是回读它。
答案 0 :(得分:5)
MySQL将使用列的排序规则作为索引。因此,如果您创建一个utf8_unicode_ci字段,那么索引也将有效地处于utf8_unicode_ci顺序。
请记住,使用索引并不总是100%绕过性能影响,但对于大多数实际用途,它会。
许多数据库系统不受CPU限制,所以我怀疑你会注意到这种影响。
答案 1 :(得分:5)
我认为btree结构会有所不同,因为它必须以不同的方式比较列值。
看看这两个查询计划:
mysql> explain select * from sometable where keycol = '3';
+----+-------------+-------+------+---------------+---------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-------+------+--------------------------+
| 1 | SIMPLE | pro | ref | PRIMARY | PRIMARY | 66 | const | 34 | Using where; Using index |
+----+-------------+-------+------+---------------+---------+---------+-------+------+--------------------------+
mysql> explain select * from sometable where binary keycol = '3';
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
| 1 | SIMPLE | pro | index | NULL | PRIMARY | 132 | NULL | 14417 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+
如果我们更改了比较的校对,突然它甚至不能再搜索索引并且必须扫描每一行。例如,无论排序规则如何,存储在索引中的实际值都是相同的,因为无论是使用区分大小写还是不区分大小写的排序规则,它仍将返回其原始大小写中的值。
因此,针对不区分大小写的排序规则的查找应该效率低一些。
然而,我怀疑你是否能够注意到这种差异;请注意,默认情况下,MySQL会使所有内容不区分大小写,因此影响不会那么糟糕。
更新:
您可以通过操作看到类似的效果:
mysql> explain select * from sometable order by keycol collate latin1_general_cs;
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-----------------------------+
| 1 | SIMPLE | pro | index | NULL | PRIMARY | 132 | NULL | 14417 | Using index; Using filesort |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-----------------------------+
mysql> explain select * from sometable order by keycol ;
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
| 1 | SIMPLE | pro | index | NULL | PRIMARY | 132 | NULL | 14417 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
请注意执行查询所需的额外“filesort”阶段。这意味着mysql将结果排队到临时缓冲区中,并在额外阶段使用快速排序对其自身进行排序,抛弃索引顺序。使用原始排序规则这一步是不必要的,因为mysql最初知道索引的顺序。