我遇到过这样的情况:我在 where 子句中指定最多 100 个主键。
示例查询:
select product_id, max(date_created) AS last_order_date
from orders
where product_id=28906
or product_id=28903
or product_id=28897
or product_id=28848
or product_id=28841
or product_id=28839
or product_id=28838
or product_id=28837
or product_id=28833
or product_id=28832
or product_id=28831
or product_id=28821
or product_id=28819
or product_id=28816
or product_id=28814
or product_id=28813
or product_id=28802
or product_id=28800
or product_id=28775
or product_id=28773
group by product_id
order by date_created desc
EXPLAIN 显示使用索引条件;使用临时的;使用文件排序
我知道我应该避免使用 Usingtemporary; 进行查询。使用 filesort
,但是即使对于大型数据集查询执行时间也很快,我是否必须避免它?我已经给出了 ID 列表,因此该查询是我能做的最好的事情。
如果我决定继续使用该查询,会出现哪些副作用或缺点?
解释输出:
1 SIMPLE wc_order_product_lookup range product_id product_id 8 NULL 3 Using index condition; Using temporary; Using filesort
最佳答案
按照戈登所说的去做,但是使用
ORDER BY last_order_date DESC
order by date_created desc
没有意义。
如果列表“太长”,它可能切换到表扫描。这可能是 MySQL 和 MariaDB 之间 EXPLAIN
的差异。 (结果集将是相同的。)
如果您执行EXPLAIN FORMAT=JSON SELECT ...
,您可能会发现有两种文件类型。
回到你原来的问题...
“文件排序”和“使用临时”在某些情况下是必要的——尤其是像你的情况。对结果进行GROUP
后,ORDER BY
调用以GROUP BY
未指定的方式进行排序。这需要存储数据并对其进行排序。
“FILEsort”是一个用词不当。在大多数情况下,行位于 RAM 中并且可以非常快速地排序。对于非常大的结果集和其他复杂的情况,实际上将使用“临时”"file"。
优化器将您的OR
列表转换为IN
,就像戈登的答案一样。所以,两种写法本质上没有区别。 (我发现 IN
更干净、更简洁。)
使用索引条件
意味着InnoDB正在承担通用“Handler”通常所做的一些工作。 (这很好,但没什么大不了的。)但是,用 INDEX(product_id, date_created)
替换 INDEX(product_id)
可能会更好,因为它是“覆盖”,这将由使用索引
表示。
“我对两个字段都有索引”——这与我推荐的复合索引不同。
你说“100个主键”,但我怀疑你的意思是“辅助”键。请提供SHOW CREATE TABLE 命令
来讨论这个问题。
我不同意老太太的故事:“应该避免使用临时查询;使用文件排序”。这些只是表明您正在做需要如此复杂的事情的线索。它很少是“避免”的。
关于mysql - 使用临时文件和文件排序总是不好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68425953/