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

gre*_*emo 2 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
);
Run Code Online (Sandbox Code Playgroud)

所以MySQL应该WHERE name = 'tag' and type = 'cat'只在搜索中使用索引(仅限最左边的前缀)WHERE type = 'tag'.

我做了:

EXPLAIN SELECT * FROM meta WHERE type = 'tag'
Run Code Online (Sandbox Code Playgroud)

结果是(第五栏possible_keys):

'1', 'SIMPLE', 'meta', 'ALL', NULL, NULL, NULL, NULL, '1', 'Using where'
Run Code Online (Sandbox Code Playgroud)

我确定我错过了一些东西,却找不到什么.任何线索?

Mar*_*ins 9

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

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

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