为什么这里不使用 s 上的索引进行排序?

发布于 2024-08-25 19:26:08 字数 1527 浏览 1 评论 0原文

设置:

mysql> create table test(id integer unsigned,s varchar(30));
Query OK, 0 rows affected (0.05 sec)

mysql> insert into test(id,s) value(1,'s');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id,s) value(1,'tsr');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id,s) value(1,'ts3r');
Query OK, 1 row affected (0.00 sec)

mysql> create index i_test_id on test(id);
Query OK, 3 rows affected (0.08 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> create index i_test_s on test(s);
Query OK, 3 rows affected (0.05 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>  insert into test(id,s) value(21,'ts3r');
Query OK, 1 row affected (0.00 sec)

然后运行这个:

mysql> explain select * from test where id in (1) order by s desc;
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | Extra                       |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | test  | ref  | i_test_id     | i_test_id | 5       | const |    2 | Using where; Using filesort |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
1 row in set (0.02 sec)

我们可以看到它使用文件排序而不是使用 s 上的索引,当选择的结果集很大时,这会很慢。如何优化?

Setup:

mysql> create table test(id integer unsigned,s varchar(30));
Query OK, 0 rows affected (0.05 sec)

mysql> insert into test(id,s) value(1,'s');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id,s) value(1,'tsr');
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id,s) value(1,'ts3r');
Query OK, 1 row affected (0.00 sec)

mysql> create index i_test_id on test(id);
Query OK, 3 rows affected (0.08 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> create index i_test_s on test(s);
Query OK, 3 rows affected (0.05 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>  insert into test(id,s) value(21,'ts3r');
Query OK, 1 row affected (0.00 sec)

And then run this:

mysql> explain select * from test where id in (1) order by s desc;
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | Extra                       |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | test  | ref  | i_test_id     | i_test_id | 5       | const |    2 | Using where; Using filesort |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----------------------------+
1 row in set (0.02 sec)

We can see it uses filesort instead of using the index on s,which will be slow when the selected result set is big.How to optimize it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小猫一只 2024-09-01 19:26:08

有时 MySQL 不使用索引,即使有可用的索引。发生这种情况的一种情况是优化器估计使用索引将需要 MySQL 访问表中很大比例的行。

来自:MySQL 5.1参考手册:MySQL如何使用索引

Sometimes MySQL does not use an index, even if one is available. One circumstance under which this occurs is when the optimizer estimates that using the index would require MySQL to access a very large percentage of the rows in the table.

From: MySQL 5.1 Reference Manual: How MySQL Uses Indexes

酒浓于脸红 2024-09-01 19:26:08

id 上的索引用于标识要返回的行。根据您使用的 MySQL 版本,它可能只允许每个表使用一个索引,并且优化器已确定使用索引来过滤行而不是排序更有效。

The index on id is being used to identify the rows to return. Depending on the version of MySQL you are using, it may only allow the use of one index per table, and the optimizer has determined it is more efficient to use the index for filtering the rows rather than for ordering.

剑心龙吟 2024-09-01 19:26:08

在“id”列上创建聚集索引。
聚集索引意味着物理排序。这样我猜测调用此查询时不会有文件排序。

但一张表只能有一个聚集索引。因此,如果您有另一列作为表的主键,则可能无法在列“id”上创建聚集索引。
因为主键默认是聚集的。

Create a clustered index on the column 'id'.
Clustered index means a physical sort. That way I am guessing there wont be a filesort, when this query is invoked.

But a table can have only one clustered index. Hence , if you have another column that is a primary key for the table, you may not be able to create a clustered index on column 'id'.
As primary keys by default are clustered.

北风几吹夏 2024-09-01 19:26:08

您使用的是哪个版本的 MySQL?直到版本 5,MySQL 才可以为每个表使用多个索引。

要使用的索引的选择还取决于结果集的大小。由于结果中仅返回两条记录,因此它可能不会使用索引。对于如此小的结果集,MySQL 似乎并不介意手动排序。

然而,如果这对您来说是一个常见的查询,那么您可以做的真正帮助 MySQL 的事情是添加一个复合索引('id','s')。基本上,这几乎就像您创建另一个小表,该表始终按 id 然后 s 排序,因此不需要文件排序,并且只需要一个索引,而不是两个。

What version of MySQL are you on? Not until version 5 could MySQL use more than one index per table.

The choice of the indexes to use also depends on the size of the result set. With only two records returned in the result, it may not use the index anyway. For such small result sets, MySQL doesn't seem to mind sorting things manually.

However, what you could do to really help MySQL out, if this is a common query for you, is to add a compound index ('id', 's'). Basically, it's almost like your creating another little table that is always sorted by id then s, so no filesort would be required, and it would only need the one index, not two.

惟欲睡 2024-09-01 19:26:08

您遇到的问题是由于您在 sql 语句中放置了 Order by 子句。这导致 MySql 跳过使用任何索引并对 S 进行完整排序。解释语句显示 MySql 有 i_test_id 一个可能的索引可供选择,并且键字段显示它已被选择,但它必须对 s 也进行排序。优化器选择不使用 i_test_s 作为可能的索引,因为它在性能方面的成本更高。您可以通过以磁盘空间为代价构建复合索引来解决此问题,也可以使用联合来以不同的方式构建查询。不过还没有在你的例子中尝试过。

The problem you are experiencing is coming from the fact that you are putting an Order by clause in your sql statement. This is causing MySql to skip using any of the indexes and doing a full sort on S. The explain statement is showing that MySql has the i_test_id a possible index to choose from and the key field is showing that it has been chosen, but it must perform a sort on s as well. The optimizer has chosen to not use i_test_s as a possible index because it would be more costly in term of performance. You can go around this issue by building componsite indexes at the expense of disk space, or you can structure your query differently using Unions instead. Haven't tried it in your example though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文