我如何优化这个子查询?

时间:2017-09-28 09:09:54

标签: mysql subquery query-optimization

我用连接和子查询编写查询。它的执行需要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

我的子查询工作正常,但需要花费太多时间。实际上,它找到了替代产品。如何优化子查询?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

code上的索引可能因为"前缀"而无用。 (请提供EXPLAIN SELECT ...确认。)

" 767限制在5.6"有多个解决方法; " 191修复"对你的情况来说可能是最糟糕的。我的Limits blog列出了您的修复程序和其他4个:

  • 升级到5.7.7以获得3072字节限制 - 您的云可能无法提供此功能;
  • 在VARCHAR上将255更改为191 - 您丢失的长度超过191个字符(不太可能?);
  • ALTER .. CONVERT TO utf8 - 你失去了表情符号和一些中国人;
  • (您当前的修正)使用"前缀" index - 你失去了一些性能优势。
  • 保持5.6 / 5.5 / 10.1但执行4个步骤将限制提高到3072字节(博客中的详细信息)。

请务必同时更改codealternative。如果这个建议不够,我会深入挖掘。