MySQL如何使用与索引的排序规则?

时间:2009-03-12 02:11:40

标签: mysql indexing

我想知道MySQL在生成索引时是否会将排序规则考虑在内,或者无论排序规则如何生成相同的索引,只有在以后遍历该索引时才会考虑排序规则。

出于我的目的,我想在字段上使用排序规则utf8_unicode_ci。我知道这种特殊的校对具有相对较高的性能损失,但使用它仍然很重要。

我在该字段上有一个索引,用于满足ORDER BY子句,快速检索行(避免使用filesort)。但是,我不确定使用此排序规则是否会影响从索引读回的行的速度,或者索引是否根据该排序规则将数据存储在已经标准化的状态,从而导致性能损失完全在生成索引而不是回读它。

2 个答案:

答案 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最初知道索引的顺序。