我想知道 MySQL 在生成索引时是否考虑了排序规则,或者无论排序规则如何生成的索引都是相同的,只有在稍后遍历该索引时才考虑排序规则。
出于我的目的,我想在字段上使用归类 utf8_unicode_ci。我知道这个特定的归类有相对较高的性能损失,但使用它对我来说仍然很重要。
我在该字段上有一个索引,用于满足 ORDER BY 子句,快速按顺序检索行(避免文件排序)。但是,我不确定使用此排序规则是否会影响从索引中读回行的速度,或者索引是否根据该排序规则将数据存储在已经规范化的状态中,从而导致性能下降完全用于生成索引而不是读回它。
最佳答案
我相信 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 |
+----+-------------+-------+-------+---------------+---------+---------+------+-------+-------------+
请注意执行查询所需的额外“文件排序”阶段。这意味着 mysql 将结果排队到一个临时缓冲区中,并在一个额外的阶段使用快速排序对其本身进行排序,抛出任何索引顺序。使用原始排序规则此步骤是不必要的,因为 mysql 最初知道索引的顺序。
关于mysql - MySQL 如何使用索引排序规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/637148/