为什么 MySQL 对此查询执行文件排序?
Why is MySQL performing a filesort on this query?
为什么 MySQL 对此查询执行文件排序?我只是期待 Using where
:
SELECT * FROM active_campaign_days
WHERE ad_unit_id=1
AND day='2017-12-10'
ORDER BY bid DESC, budget DESC, campaign_id ASC
(ad_unit_id, day, bid, budget, campaign_id)
上的索引 - 数据库根据 EXPLAIN
使用此索引。
在这个特定的结果集中,bid
和 budget
对于所有行都是相同的。 (ad_unit_id, campaign_id)
是独一无二的。
解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE active_campaign_days ref ad_unit_id,ad_unit_id_2 ad_unit_id_2 7 const,const 5 Using where; Using filesort
让我们剖析查询..
WHERE ad_unit_id=1 AND day='2017-12-10'
需要一个以 ad_unit_id
和 day
开头的索引(顺序不限)。这将提供最佳过滤。
如果可行,可以将所有 ORDER BY
添加到 INDEX
中,这样就可以避免对数据进行排序。但是 ORDER BY bid DESC, budget DESC, campaign_id ASC
有一个问题。请注意,混合了 DESC
和 ASC
。 MySQL 只能在一个方向上扫描一个索引。这意味着全部必须是 ASC
或全部必须是 DESC
。 (请参阅下面的注释)因此,INDEX(ad_unit, day, bid, budget, campaign_id)
没有您想要的那么有用。
如果优化器可以通过第 2 步,则在 SELECT
中添加 任何地方 提到的任何其他列(即所有 *
),那么索引就会变成 "covering"。这提供了不同种类的性能提升——通过在索引中完成所有工作,而不必触及 'data'.
注意:从 8.0 版开始,MySQL 将在索引声明中遵循 DESC
。因此,您可以说 INDEX(ad_unit, day, bid DESC, budget DESC, campaign_id ASC)
,优化器可以使用它 而无需在上面的第 2 项中排序 。 (8.0 之前,DESC
在索引声明中被允许,但被忽略。)
解决方法?它会改变输出的顺序,但您可能会接受所有列 ASC
(或所有 DESC
)?
与此同时,INDEX(ad_unit_id, day)
就是所有值得拥有的东西。
为什么 MySQL 对此查询执行文件排序?我只是期待 Using where
:
SELECT * FROM active_campaign_days
WHERE ad_unit_id=1
AND day='2017-12-10'
ORDER BY bid DESC, budget DESC, campaign_id ASC
(ad_unit_id, day, bid, budget, campaign_id)
上的索引 - 数据库根据 EXPLAIN
使用此索引。
在这个特定的结果集中,bid
和 budget
对于所有行都是相同的。 (ad_unit_id, campaign_id)
是独一无二的。
解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE active_campaign_days ref ad_unit_id,ad_unit_id_2 ad_unit_id_2 7 const,const 5 Using where; Using filesort
让我们剖析查询..
WHERE ad_unit_id=1 AND day='2017-12-10'
需要一个以ad_unit_id
和day
开头的索引(顺序不限)。这将提供最佳过滤。如果可行,可以将所有
ORDER BY
添加到INDEX
中,这样就可以避免对数据进行排序。但是ORDER BY bid DESC, budget DESC, campaign_id ASC
有一个问题。请注意,混合了DESC
和ASC
。 MySQL 只能在一个方向上扫描一个索引。这意味着全部必须是ASC
或全部必须是DESC
。 (请参阅下面的注释)因此,INDEX(ad_unit, day, bid, budget, campaign_id)
没有您想要的那么有用。如果优化器可以通过第 2 步,则在
SELECT
中添加 任何地方 提到的任何其他列(即所有*
),那么索引就会变成 "covering"。这提供了不同种类的性能提升——通过在索引中完成所有工作,而不必触及 'data'.
注意:从 8.0 版开始,MySQL 将在索引声明中遵循 DESC
。因此,您可以说 INDEX(ad_unit, day, bid DESC, budget DESC, campaign_id ASC)
,优化器可以使用它 而无需在上面的第 2 项中排序 。 (8.0 之前,DESC
在索引声明中被允许,但被忽略。)
解决方法?它会改变输出的顺序,但您可能会接受所有列 ASC
(或所有 DESC
)?
与此同时,INDEX(ad_unit_id, day)
就是所有值得拥有的东西。