Tom*_*Tom 8 innodb mariadb index covering-index
我有以下查询,使用 MariaDB 10 / InnoDB:
SELECT id, sender_id, receiver_id, thread_id, date_created, content
FROM user_message
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Run Code Online (Sandbox Code Playgroud)
此查询根据给定的条件获取消息并按创建日期排序。
我有一个覆盖索引(thread_id, date_created)。
运行 EXPLAIN 时,使用了正确的索引并且我得到了输出“Using where”,尽管查询使用的是不在索引中的语句中间的列。我可以为“placeholder = x”使用任何值,结果是一样的。
如果我将排序更改为使用另一列,则 EXPLAIN 会正确指示“使用位置。使用文件排序”。
我有一个令人头疼的时刻。有人可以解释一下吗?我希望看到的是需要额外的文件排序,因为由于额外的列而无法完全使用覆盖索引。
案例 A
查询:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Run Code Online (Sandbox Code Playgroud)
指数:
(thread_id, date_created)
Run Code Online (Sandbox Code Playgroud)
计划:
Index is used
Using Where
Using filesort
Run Code Online (Sandbox Code Playgroud)
没问题吧?如果使用索引(部分匹配WHERE条件),我们仍然需要一个排序操作来对结果进行排序some_column(不在索引中)。我们还需要额外的检查(Using Where)来只保留符合第二个条件的行。好的。
案例B(问题)
查询:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Run Code Online (Sandbox Code Playgroud)
指数:
(thread_id, date_created)
Run Code Online (Sandbox Code Playgroud)
计划:
Index is used
Using Where
-- no "Using filesort"
Run Code Online (Sandbox Code Playgroud)
那么,为什么这里不需要排序呢?因为索引足以按查询需要进行排序。当然还有AND placeholder = FALSE索引未涵盖的额外条件 ( )的附加问题。
好的,但我们真的不需要在这里排序。索引可以为我们提供与第一个条件 ( WHERE thread_id = 12345)匹配的结果,并按所需的输出顺序排列。我们需要的唯一额外检查 - 以及计划所做的 - 是按照索引提供的顺序从表中获取行,并检查第二个条件,直到我们获得 20 个匹配项。这就是 **Using Where"" 的意思。
我们可能会在前 20 行(非常好且快速)或前 100 行(仍然可能足够快)或前 1000000 行(可能非常非常慢)中获得 20 个匹配项,或者我们可能仅从即使在从索引中读取所有匹配的行之后,表也是如此(在大表上真的很慢)。这一切都取决于数据的分布。
案例 C(甚至更好的计划)
查询:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Run Code Online (Sandbox Code Playgroud)
指数:
(placeholder, thread_id, date_created)
Run Code Online (Sandbox Code Playgroud)
计划:
Index is used
-- no "Using Where"
-- no "Using filesort"
Run Code Online (Sandbox Code Playgroud)
现在我们的索引同时匹配条件和排序依据。该计划非常简单:从索引中获取前* 20 个匹配项并从表中读取相应的行。不需要额外的检查(没有“使用位置”),也不需要排序(没有“使用文件排序”)。
first*:从末尾向后读取索引时的前 20 个(如我们所见ORDER BY .. DESC),但这不是问题。B-tree 索引可以以几乎相同的性能向前和向后读取。
SELECT中的任何位置。因此,您没有“覆盖”索引。并且为您的查询创建覆盖索引是不切实际的(提到的列太多)。GROUP BY x ORDER BY b)其中任何一个都可以只查看 20 行;任何其他索引都需要接触更多行,可能是整个表:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)
Run Code Online (Sandbox Code Playgroud)不,在对索引中的列进行排序时,复合索引组件的基数无关紧要。
我的食谱解释了如何在给定SELECT.
| 归档时间: |
|
| 查看次数: |
347 次 |
| 最近记录: |