mysql - MySQL 如何使用索引排序规则?

标签 mysql indexing

我想知道 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/

相关文章:

mysql - select查询在oracle中慢但在mysql数据库中快

php - 我想在 mysql 的 3 个表中使用左连接和内连接?

mysql - 数据库设计。一对多还是多对多?

sql-server - 非聚集索引和覆盖索引的区别

arrays - Flash AS3,如何使用整数键索引 HashMap

PostgreSQL 忽略了我的复合索引

Java Web 应用程序连接到 MYSQL 和 SQL SERVER

php - 为什么此上传文件代码在 CakePHP 中不起作用

javascript - 如何根据类似的类获取容器内元素的索引?

postgresql - 具有大量列的唯一索引