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"是:
- 在索引中进行所有搜索,前提是它比 table 小得多。注意:索引是一个BTree; table 是一个不同的 BTree。
- 从步骤 1 中获取
PRIMARY KEY
个值。即获取 prod_id
. 的列表
- 通过使用
PRIMARY KEY
到 table 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
。
- 深入研究数据 40 次。
- 过滤掉不符合要求的
title
。
- 传送 3 行。
在 I/O 范围内(阅读:巨大 table),这将是 I/O 计数:
- 1 个块可能包含所有 40 个 index 条目;他们会在一起,因为索引的第一部分是相同的。
- 需要在 table 中查看近 40 个区块。
总计:约 41 个工作单元。
现在看看带有子查询的查询。
- 只扫描索引。又是 1 个方块。
- 伸入主table 4 次。
总计:4 个作业单元。
4 << 41,所以更复杂的查询实际上运行得更快。 (您不太可能真正看到完整的 10 倍改进——因为我遗漏了很多细节。)
我正在阅读 "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"是:
- 在索引中进行所有搜索,前提是它比 table 小得多。注意:索引是一个BTree; table 是一个不同的 BTree。
- 从步骤 1 中获取
PRIMARY KEY
个值。即获取prod_id
. 的列表
- 通过使用
PRIMARY KEY
到 tableproducts
. 中有效地查找其余数据 (
*
)
假设有 40 行 actor='SEAN CARREY'
,其中只有 3 有 title LIKE '%APOLLO%'
。让我们比较两种方法:
SELECT * FROM products
WHERE actor='SEAN CARREY' AND title LIKE '%APOLLO%'
- 查看
INDEX(actor, ...)
找到 40prod_id
。 - 深入研究数据 40 次。
- 过滤掉不符合要求的
title
。 - 传送 3 行。
在 I/O 范围内(阅读:巨大 table),这将是 I/O 计数:
- 1 个块可能包含所有 40 个 index 条目;他们会在一起,因为索引的第一部分是相同的。
- 需要在 table 中查看近 40 个区块。
总计:约 41 个工作单元。
现在看看带有子查询的查询。
- 只扫描索引。又是 1 个方块。
- 伸入主table 4 次。
总计:4 个作业单元。
4 << 41,所以更复杂的查询实际上运行得更快。 (您不太可能真正看到完整的 10 倍改进——因为我遗漏了很多细节。)