【问题标题】:EXPLAIN SELECT shows that MySQL is not using my indexEXPLAIN SELECT 显示 MySQL 没有使用我的索引
【发布时间】:2012-08-20 14:29:19
【问题描述】:

表定义,注意UNIQUE索引:

CREATE TABLE meta
(
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  type SET('tag', 'keyword') NOT NULL,
  name VARCHAR(255) NOT NULL,
  user_id INT UNSIGNED NOT NULL,
  UNIQUE (name, type, user_id),
  FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
);

所以 MySQL 应该在像 WHERE name = 'tag' and type = 'cat' 这样的搜索中使用索引,以及只使用(最左边的前缀)WHERE type = 'tag'

我做到了:

EXPLAIN SELECT * FROM meta WHERE type = 'tag'

结果是(第五列是possible_keys):

'1', 'SIMPLE', 'meta', 'ALL', NULL, NULL, NULL, NULL, '1', 'Using where'

我确定我错过了什么,但找不到什么。有什么线索吗?

【问题讨论】:

  • MySQL 并不总是使用索引,即使它们可用。有时进行表扫描比命中索引更快,例如当表中的数据很少时。
  • @MarcB 哦,我明白了。那么,我是否应该添加一些随机数据来检查是否会使用索引?

标签: mysql indexing database-indexes


【解决方案1】:

这种类型的解释可能已经存在很多次了......但是试图解释为什么数据库引擎通常不会在所描述的情况下使用索引(当 WHERE 子句在多列中只有第二个字段时) index),一个简单的类比可能会有所帮助。

您可以将实体电话簿(一种用纸制成的老式电话簿)视为一种索引。索引键是姓名,数据是电话号码。电话簿索引基本上是“Lastname, Firstname”的形式。如果您在电话簿中查找姓名(例如,Mark Wilkins),您正在寻找键“Wilkins,Mark”。您还可以通过姓氏轻松查找姓名,并查找给定姓氏的所有条目。

但是,在电话簿“索引”中搜索Firstname 并不容易。如果要查找电话簿中Firstname=Mark 的所有条目,则必须扫描整个电话簿。使用标准索引(例如,像 b 树之类的东西),数据库引擎也有完全相同的问题。如果 WHERE 子句仅包含双列索引的第二列,则必须扫描整个索引以查找匹配项。一些数据库引擎可能仍会这样做,但仅扫描表本身可能会更快,因为它通常必须读取表中的数据以获取结果集。

【讨论】:

  • 优秀的例子,标记为答案而不是上一个。谢谢!
【解决方案2】:

这个话题已经被another question覆盖了。

如果您希望SELECTstatement 使用您定义的唯一索引,type 必须是索引的第一个字段 (UNIQUE(type, name, user_id))。

How MySQL Uses IndexesMultiple-Column Indexes

【讨论】:

  • 也就是说,我需要在类型上添加另一个索引吗?
  • 不,更改当前 UNIQUE 索引中字段的顺序就足够了。
猜你喜欢
  • 2012-12-25
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多