MySQL 涵盖索引和 LIKE 运算符

MySQL covering indexes and LIKE operator

我正在阅读 "High Performance MySQL",O'Reilly,第 2 版。 第 122 页:

MySQL can't perform the LIKE operation in the index. etc

在同一个页面,后面的例子是(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

然后是:

Now MySQL uses the covering index in the first stage of the query, when it finds matching rows in the subquery in the FROM clause.

我不明白为什么,LIKE语句还在...

由于索引是从左到右工作的,因此如果您想使用索引-

,则左侧不应可变

如果您的标题字段已编入索引,请按照以下检查-

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

在你的情况下 sub-query 不是必需的,因为你可以通过简单的查询获得相同的结果,如果 actor 字段被索引,那么查询将只使用这个索引。

假设 table 是InnoDB

SELECT prod_id
     FROM products
     WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'

INDEX(actor, title, prod_id)中处理,因为它是"covering"

SELECT * FROM ...

不是 "covered" 因为(我假设)*.

中还有很多其他字段

他们展示的"trick"是:

  1. 在索引中进行所有搜索,前提是它比 table 小得多。注意:索引是一个BTree; table 是一个不同的 BTree。
  2. 从步骤 1 中获取 PRIMARY KEY 个值。即获取 prod_id.
  3. 的列表
  4. 通过使用 PRIMARY KEY 到 table products.
  5. 中有效地查找其余数据 (*)

假设有 40 行 actor='SEAN CARREY',其中只有 3 title LIKE '%APOLLO%'。让我们比较两种方法:

SELECT * FROM products
    WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'
  1. 查看 INDEX(actor, ...) 找到 40 prod_id
  2. 深入研究数据 40 次。
  3. 过滤掉不符合要求的title
  4. 传送 3 行。

在 I/O 范围内(阅读:巨大 table),这将是 I/O 计数:

  1. 1 个块可能包含所有 40 个 index 条目;他们会在一起,因为索引的第一部分是相同的。
  2. 需要在 table 中查看近 40 个区块。

总计:约 41 个工作单元。

现在看看带有子查询的查询。

  1. 只扫描索引。又是 1 个方块。
  2. 伸入主table 4 次。

总计:4 个作业单元。

4 << 41,所以更复杂的查询实际上运行得更快。 (您不太可能真正看到完整的 10 倍改进——因为我遗漏了很多细节。)