EXPLAIN SELECT显示MySQL没有使用我的索引

时间:2012-08-20 14:29:20

标签: mysql indexing database-indexes

表定义,请注意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'

我确定我错过了什么,却找不到什么。任何线索?

2 个答案:

答案 0 :(得分:9)

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

您可以将物理电话簿(其中一种由纸张制成的老式电话簿)视为一种索引。索引键是名称,数据是电话号码。电话簿索引基本上是“Lastname, Firstname”形式。如果你在电话簿中查找一个名字(例如Mark Wilkins),那么你正在寻找关键词“Wilkins,Mark”。您也可以通过姓氏轻松查找名称,并查找给定姓氏的所有条目。

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

答案 1 :(得分:1)

another question已涵盖此主题。

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

请参阅How MySQL Uses IndexesMultiple-Column Indexes