为什么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
答案 0 :(得分:3)
让我们剖析查询..
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
(即所有*
)中添加 的任何其他列,那么索引会来“覆盖”。这提供了不同的性能提升 - 通过在索引中完成所有工作,而不必触及'数据'。
注意:从版本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)
就是值得拥有的一切。