我如何优化这个子查询?
Posted
技术标签:
【中文标题】我如何优化这个子查询?【英文标题】:How I can optimize this subquery? 【发布时间】:2017-09-28 09:09:54 【问题描述】:我编写了一个带有连接和子查询的查询。它的执行需要 2 分钟。优化不了怎么办?有什么建议吗?
select oli.*,oli2.* from order o
LEFT JOIN order_line_item oli ON oli.order_id = o.id
LEFT JOIN order_line_item oli2 ON oli2.id
= (SELECT oli3.id FROM order_line_item oli3
WHERE oli3.order_id = o.id
AND oli.code = oli3.alternative
GROUP BY oli3.code, o.id
LIMIT 1) WHERE o.store_id != 100 GROUP BY oli.code, oli2.code, o.id
我的子查询可以正常工作,但需要花费太多时间。实际上,它找到了替代产品。如何优化我的子查询?
【问题讨论】:
请为您的查询中涉及的所有表提供SHOW CREATE TABLE <tablename>
输出。
还有,有必要选择*
吗?如果您不需要所有列,则可能会根据我们从您的表结构(评论上方)中了解到的内容以及您确实需要的列进行改进。
因为*
,这听起来像是对GROUP BY
的无效使用。
请用英文解释查询的目的。 (这个查询太复杂了,我无法理解。我认为可能有更简单的方法来处理它。)
认为有订单。该订单有 11 个项目(产品)存储在订单行项目表中。一种产品已完成,系统具有该成品的替代产品。我必须分别计算给客户的产品数量和替代产品的数量。产品的alternated_to 列分配给替代产品的代码。所以我使用了oli.code = oli3.alternative。它工作正常,但我的子查询花费了太多时间@RickJames
【参考方案1】:
oli2 ON
中的子查询是导致运行缓慢的原因,因为它需要为每一行执行。可以简化为:
SELECT
oli.*,
oli2.*
FROM order o
LEFT JOIN order_line_item oli
ON oli.order_id = o.id
LEFT JOIN order_line_item oli2
ON (
o.id = oli2.order_id
AND
oli.code = oli2.alternative
)
WHERE o.store_id != 100
GROUP BY oli.code, oli2.code, o.id
【讨论】:
谢谢,但还是很慢【参考方案2】:code
上的索引可能因为“前缀”而无用。 (请提供EXPLAIN SELECT ...
确认。`)
“5.6 中的 767 限制”有多种解决方法; “191 修复”对于您的情况可能是最糟糕的。我的Limits blog 列出了您的修复和其他 4 个:
升级到 5.7.7 以获得 3072 字节的限制——您的云可能不提供此功能; 在 VARCHAR 上将 255 更改为 191 -- 您会丢失任何超过 191 个字符的值(不太可能?);ALTER .. CONVERT TO utf8
-- 你失去了表情符号和一些中文;
(您当前的修复)使用“前缀”索引——您会失去一些性能优势。
保留 5.6/5.5/10.1,但执行 4 个步骤将限制提高到 3072 字节(博客中的详细信息)。
请务必同时更改 code
和 alternative
。如果这个建议还不够,我会深入挖掘。
【讨论】:
以上是关于我如何优化这个子查询?的主要内容,如果未能解决你的问题,请参考以下文章