鉴于下表,为什么我的 EXPLAIN 说它没有使用任何键(特别是
tag_pos_nr
键?
CREATE TABLE `my_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag` mediumtext DEFAULT '0',
`name` mediumtext DEFAULT 'John Doe',
`pos` mediumtext DEFAULT '0',
`comment` mediumtext DEFAULT '',
`nr` int(11) DEFAULT 0,
PRIMARY KEY (`id`),
KEY `tag_pos_nr` (`tag`(20),`pos`(20),`nr`),
KEY `tag` (`tag`(20))
EXPLAIN SELECT id from my_tbl WHERE tag LIKE '%191223%' AND pos='pos1' AND nr=1;
+------+-------------+---------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | my_tbl | ALL | NULL | NULL | NULL | NULL | 14238 | Using where |
+------+-------------+---------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.000 sec)
前缀(例如
tag(20)
)实际上毫无用处。我认为我从未见过两个前缀在复合索引中有用,如您的 tag_pos_nr
.
LIKE '%...'
不能使用索引(“覆盖”除外;见下文)。
使用 that
WHERE tag LIKE '%191223%' AND pos='pos1' AND nr=1
模式可以完成的最好的事情是
INDEX(nr)
或者也许
INDEX(nr, pos(20))
WHERE
中子句的顺序并不重要(优化器会根据需要重新排列它们); INDEX
中的顺序很重要。
如果标签、名称和/或 pos 从来都不是很大,请更改为
VARCHAR(...)
并删除 INDEXes
中的前缀。
INDEX(a)
时,
INDEX(a,b)
就是多余的。
“覆盖”索引是包含查询中任何地方使用的所有列的索引。注意:前缀不允许“覆盖”,因为索引中缺少部分列。