【问题标题】:MySQL datetime index is not workingMySQL 日期时间索引不起作用
【发布时间】:2011-04-30 02:57:23
【问题描述】:

表结构:

+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| id          | int(11)  | NO   | PRI | NULL    | auto_increment |
| total       | int(11)  | YES  |     | NULL    |                |
| thedatetime | datetime | YES  | MUL | NULL    |                |
+-------------+----------+------+-----+---------+----------------+

总行数:137967

mysql> explain select * from out where thedatetime <= NOW();
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | out         | ALL  | thedatetime   | NULL | NULL    | NULL | 137967 | Using where |
+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+

真正的查询要长得多,有更多的表连接,关键是,我无法让表使用datetime 索引。如果我想在某个日期之前选择所有数据,这对我来说会很困难。但是,我注意到如果我选择较小的数据子集,我可以让 MySQL 使用索引。

mysql> explain select * from out where thedatetime <= '2008-01-01';
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+
| id | select_type | table       | type  | possible_keys | key         | key_len | ref  | rows  | Extra       |
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+
|  1 | SIMPLE      | out         | range | thedatetime   | thedatetime | 9       | NULL | 15826 | Using where |
+----+-------------+-------------+-------+---------------+-------------+---------+------+-------+-------------+

mysql> select count(*) from out where thedatetime <= '2008-01-01';
+----------+
| count(*) |
+----------+
|    15990 |
+----------+

那么,我该怎么做才能确保无论我输入什么日期,MySQL 都会使用索引?

【问题讨论】:

  • EXPLAIN 告诉您索引已“使用”,或者更准确地说,它已考虑 - 在这两种情况下。我在下面的回答详细解释了。另一方面,如果您遇到表现不佳,那么您就过于简化了问题。

标签: mysql database-design


【解决方案1】:

一切都按预期进行。 :)

索引可以加快检索速度。他们使用索引查找来做到这一点。

在您第一次查询时未使用索引,因为您正在检索所有行,在这种情况下使用索引较慢(lookup indexget rowlookup indexget row... x 行数比get all rows慢==表扫描)

在第二个查询中,您只检索部分数据,在这种情况下,表扫描要慢得多。

优化器的工作是使用 RDBMS 保存在索引上的统计信息来确定最佳计划。在第一种情况下考虑了索引,但规划者(正确地)将其丢弃了。

编辑
您可能想阅读 this 之类的内容,以了解有关 mysql 查询计划器的一些概念和关键字。

【讨论】:

  • 我想这就是原因(我尝试将此答案应用于其他表)。我需要阅读有关 MySQL 索引的更多信息,因此感谢您提供的链接。
  • 当他在第二个查询上运行解释子句时,在 Extra 列中显示“使用 where”,这不意味着它是全表扫描吗?
【解决方案2】:

这里有两件事在起作用 -

  1. 索引的选择性不够 - 如果索引覆盖的范围超过大约。 30% 的行,MySQL 将决定全表扫描更有效。当你收缩索引开始的范围时。

  2. 连接中每个表一个索引

真正的查询要长得多 有了更多的表连接,重点是......

关键是因为它有可能无法使用该索引的连接。 MySQL 可以在连接中为每个表使用一个索引(除非它符合index-merge 优化条件)。如果主键已用于连接,则不会使用日期时间。为了使用它,您需要以正确的顺序在连接键 + 日期时间索引上创建一个多列索引。

检查实际查询的 EXPLAIN 以查看 MySQL 用于连接的键。修改该索引以包含 thedatetime 列,或者从两者创建一个新的多列索引(取决于您使用连接键的目的)。

【讨论】:

  • 感谢第一个答案和解释,但我必须标记 Unreason,因为他/她先回答。
  • 他很好地解释了为什么非选择性索引的索引查找速度较慢
猜你喜欢
  • 1970-01-01
  • 2018-01-24
  • 2020-05-27
  • 2015-02-15
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
相关资源
最近更新 更多