我正在阅读"高性能MySQL",O' Reilly,第2版。 第122页:
MySQL无法在索引中执行LIKE操作。等
在同一页面中,后续示例是(其中有一个关于actor,title,prod_id的索引):
EXPLAIN SELECT *
FROM products
JOIN (
SELECT prod_id
FROM products
WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'
)
AS t1 ON (t1.prod_id=products.prod_id)\G
然后它说:
现在MySQL在查询的第一阶段使用覆盖索引,当它在FROM子句中的子查询中找到匹配的行时。
我不明白为什么,LIKE声明仍然存在......
答案 0 :(得分:2)
我假设表格为InnoDB
。
SELECT prod_id
FROM products
WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'
在INDEX(actor, title, prod_id)
处理,因为它是“覆盖”
SELECT * FROM ...
未被“覆盖”,因为(我假设)*
中有很多其他字段。
他们展示的“技巧”是:
PRIMARY KEY
值。即获取prod_id
的列表。*
进入表格PRIMARY KEY
,有效地查找其余数据(products
)。假设共有40行actor='SEAN CARREY'
,其中只有3行 title LIKE '%APOLLO%'
。让我们比较两种方法:
SELECT * FROM products
WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'
INDEX(actor, ...)
以查找40 prod_id
。title
。在I / O界限中(读取:巨大的表),这将是I / O计数:
总计:约41个单位的工作。
现在用子查询查看查询。
总计:4个工作单位。
4<< 41,因此更复杂的查询实际上运行得更快。 (你不太可能真正看到完整的10倍改进 - 因为我遗漏了很多细节。)
答案 1 :(得分:0)
因为索引是从左到右工作所以如果你想使用索引 -
,左边不应该是变量如果您的标题字段已编入索引,请按以下方式检查 -
title like '%APOLLO%' : Will not use index
title like '%APOLLO' : Will not use index
title like 'APOLLO%' : Will use index
title like 'APOLLO' : Will use index
在您的情况下,不需要子查询,因为您可以通过简单查询获得相同的结果,并且如果actor字段被索引,则查询将仅使用此索引。