这就是我的所作所为:
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” - >空值。我该怎么做才能加快速度:
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
答案 0 :(得分:2)
MySQL(和MariaDB)无法有效地使用索引来满足谓词。
name LIKE '%poor%'
考虑满足该条件的name
的可能值,以及它们可能出现在索引中的位置。例如,值'aaapoor'
和'zzzpoor' satisfy the condition
。满足条件的值可以在索引中出现 anywhere ,作为索引中的第一个值/行,或索引中的最后一个值/行,或者介于两者之间的任何位置。
因此,MySQL必须为表中的每个行评估该谓词。必须检查每一行。
MySQL无法使用索引来消除任何行的检查。索引提高谓词(如col = 'foo'
)性能的方式是,MySQL可以非常快速地消除需要检查 not 的大量行,因为它们出现在哪里指数。 MySQL可以快速消除大量的行,并缩小需要检查的索引页面。这就是索引如何提高性能。
MySQL无法通过查询中的谓词来做到这一点。这就是为什么没有使用索引的原因。
如果有"覆盖"对于查询的索引,MySQL可能会使用它。例如,如果您只选择name
列,则MySQL可以仅从索引页面满足查询,而无需访问基础数据页。
或者,如果你有"顺序"在name
(或索引中的一个或多个前导列)上,MySQL可能会使用索引来避免使用"使用filesort"操作
如果你想搜索"单词"出现在VARCHAR列中,您可能需要考虑使用FULLTEXT索引。在旧版本的MySQL中,仅在MyISAM表上支持这些版本。较新版本(> = 5.6?)的MySQL也支持InnoDB表上的FULLTEXT索引。
全文搜索在谓词中使用不同的操作(它的不与LIKE
进行比较。)