为什么 mysql 不将密钥用于简单的 select?

Why doesnt mysql use the key for a simple select?

这是我所做的:

MariaDB []> explain select * from blabla where name like '%poor%';
+------+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
| id   | select_type | table        | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+------+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
|    1 | SIMPLE      | blabla       | ALL  | NULL          | NULL | NULL    | NULL | 8358772 | Using where |
+------+-------------+--------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.01 sec)

MariaDB [bd]>show create table blabla;
| blabla | CREATE TABLE `blabla` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`(252))
) ENGINE=InnoDB AUTO_INCREMENT=8372852 DEFAULT CHARSET=utf8

因此,如果您观看:'name' 上有一个键,解释告诉我 "possible_keys" -> NULL。我该怎么做才能让它更快:

MariaDB []>select * from blabla where name like '%poor%';
********
********
491 rows in set (26.20 sec)
MariaDB []>WHAT??? 26 seconds on a 8 373 116 rows table? ARE YOU KIDDIN'?
ERROR 1064 (42000): You have an error

MySQL(和MariaDB)无法有效利用索引来满足谓词。

name LIKE '%poor%'

考虑满足该条件的 name 的可能值,以及它们可能出现在索引中的位置。例如,值 'aaapoor''zzzpoor' satisfy the condition。满足条件的值可以出现在索引中的 任何地方 ,作为索引中的第一个 value/row,或作为索引中的最后一个 value/row,或任何地方介于两者之间。

因此,MySQL 必须为 table 中的 每个 行评估该谓词。必须检查每一行。

MySQL 不能使用索引来消除 any 行被检查。索引提高 col = 'foo' 等谓词性能的方式是 MySQL 可以非常快速地消除大量 not 需要检查的行,因为它们出现在索引中的位置。 MySQL 可以快速消除大量行,并缩小需要检查的索引页面。这就是索引提高性能的方式。

并且 MySQL 不能用您查询中的谓词来做到这一点。这就是没有使用索引的原因。


如果查询有 "covering" 索引,MySQL 可能会使用它。例如,如果您仅选择 name 列,则 MySQL 可以仅从索引页满足查询,而无需访问基础数据页。

或者,如果您在 name 上有一个 "order by"(或索引中的一个或多个前导列),MySQL 可能会使用索引来避免 "Using filesort" 操作.


如果要搜索出现在 VARCHAR 列中的 "words",您可能需要考虑使用 FULLTEXT 索引。在 MySQL 的旧版本中,这些仅在 MyISAM table 上受支持。 MySQL 的较新版本(>=5.6?)也支持 InnoDB table 上的 FULLTEXT 索引。

全文搜索在谓词中使用不同的操作(不是 LIKE 比较。)