【问题标题】:Using IN() clause resulting in Filesort使用 IN() 子句导致 Filesort
【发布时间】:2013-02-06 10:41:12
【问题描述】:

我有一张简单的桌子 ->

id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
by_id INT UNSIGNED NOT NULL
posted_on INT UNSIGNED NOT NULL

我的表引擎是MyISAM

我在by_id,posted_on,id 上有一个名为combo1 的多列索引

我运行这个查询 ->

EXPLAIN SELECT * FROM books 
        WHERE by_id = '1' AND posted_on = '0' 
        ORDER BY id DESC LIMIT 7;

Extra 列显示Using where,键列显示combo1

但是,当我运行这个查询时 ->

EXPLAIN SELECT * FROM books 
        WHERE by_id IN(1,7,10) AND posted_on = '0' 
        ORDER BY id DESC LIMIT 7;

Extra 列显示Using where; Using filesort,键列显示combo1

即使 QEP 显示优化器正在使用索引 combo1,其中包含“id”索引,为什么在第二种情况下会出现 filesort

【问题讨论】:

    标签: mysql explain filesort


    【解决方案1】:

    索引是 B+ 树。这意味着在 by_id 1 下有所有的记录都以 posted_on 0 和 by_id 1,然后你就有了这些记录的所有 id。但是,在 by_id 7 下,您有另一个树分支,其中包含带有 posted_on 0 的记录,并且它们包含带有其 id 的记录。

    当你有 in 子句时,你正在检索树的 3 个不同的分支,你必须合并它们并重新使用它们,因为 1,2,4 的 id 可能在 by_id 1 下,但 3,5 在 by_id 10 下; MySQL 检索到 1,2,4,3,5 并且必须使用它们。

    第一种情况只有一个分支,每个分支都已经排序

    【讨论】:

    • 感谢@Darhazer 的精彩解释
    • 请告诉我是否应该从 combo1 索引中删除 id.. @Darhazer
    • 好吧,我不确定 MySQL 是否利用了分支已经排序的优势并应用了 merge_sort;也许它也取决于版本。如果没有适当的基准测试,我会在索引中保留 id。另一方面,如果表是 InnoDB,则 id 包含在每个二级索引的末尾。如果我没记错的话,仅在 MySQL 5.6 中进行排序时才考虑到这一点。
    猜你喜欢
    • 2012-08-08
    • 2017-07-13
    • 2010-09-14
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 2011-09-17
    • 2014-07-17
    相关资源
    最近更新 更多