2

表定义,注意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'以及 only (leftmost prefixing) WHERE type = 'tag'

我做了:

EXPLAIN SELECT * FROM meta WHERE type = 'tag'

结果是(第五列是possible_keys):

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

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

4

2 回答 2

9

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

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

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

于 2012-08-20T15:28:15.450 回答
2

这个话题已经被另一个问题所涵盖。

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

查看MySQL 如何使用索引多列索引

于 2012-08-20T14:39:09.397 回答