MYSQL 查询优化:减少条件中的内部查询

3
我遇到了一个小问题,
这是一个演示查询。
select 
    A.order_id, 
    if(
         A.production_date != '0000-00-00', 
         A.production_date,
         if(
              SOME INNER QUERY != '0000-00-00', 
              SOME INNER QUERY ,
              SOME OTHER INNER QUERY
           )
    ) as production_start_date
from
    orders A

所以,假设SOME INNER QUERY花费了10秒钟进行计算,从8个不同的表中获取数据,检查相同订单类型的历史记录等,并且如果其结果是一个日期,则在第一个条件中获取该日期。但现在它将需要20秒,因为需要10秒钟计算if条件,再用10秒钟重新执行以返回结果。
有没有办法减少这个时间?
如果有人对实际查询感兴趣,请访问http://pastebin.com/zqzbpEei

1
+1 是因为你没有在问题中包含那堵代码墙。 - ypercubeᵀᴹ
3
我的建议是将现在的“相关子查询”重写为主查询中FROM子句中的LEFT JOIN。这样做有两个可能会提高效率的原因:1.它们不必计算两次,2.它们不必为每一行“订单”运行一次。 - ypercubeᵀᴹ
1
我查看了你在http://pastebin.com/zqzbpEei中放置的SQL查询。太糟糕了。你是怎么写这个查询的?如果你编写一个简单的存储过程,使用临时表而不是编写如此庞大的查询,会更好。 - Krishna Rani Sahoo
你说得没错,但这就是PHP if else条件语句的最终结果。而且有不同的函数来创建查询的不同部分。最后一个函数是将所有部分组合起来并生成一个大查询... :) - Aamir Mahmood
1
将所有部分拆分为存储过程。在主查询中调用所有存储过程。我在您的查询中看到,类似类型的计算被执行了很多次。您可以将它们保存到临时文件中,并在查询中使用它。如果您清楚地说明您的表格,提供一些示例数据和输出数据,则会更好。然后我们可以建议如何简化它。 - Krishna Rani Sahoo
显示剩余3条评论
1个回答

1
假设您的查询看起来像这样(抱歉,我放弃了寻找实际查询):
IF(
    (SELECT aField FROM aTable WHERE bigCondition) != '0000-00-00',
    SELECT aField FROM aTable WHERE bigCondition,
    SELECT anotherField FROM anotherTable
)

你可以将其重写为以下内容:
SELECT IF (
    someField != '0000-00-00',
    someField,
    SELECT anotherField FROM anotherTable
)
FROM aTable WHERE bigCondition

这样你只需要计算一次bigCondition
这个查询确实很丑陋。
你的主要问题似乎是滥用(和滥用)IF()结构。它应该保留给简单的条件和操作。逻辑运算符也是如此。不要对整个查询进行操作。例如,我看到在你的查询中有一小部分出现了几次:
IF(
    (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id) IS NULL
       OR (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id) = '',
    '6', -- by the way, why is this a string?! This is an integer, isn't it?
    (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id)
)

这是不好的。条件应该直接移到 SELECT 语句中。重写如下:

SELECT
    IF (v1.weekends IS NULL OR v1.weekends = '', 6, v1.weekends)
FROM vendor v1 WHERE v1.vendor_id = A.vendor_id

这是两个SELECT的保存。对于包含查询的每个IF()都要这样做,我敢打赌,您将大大加快查询速度。
关于您当前的代码还有很多要说的。不幸的是,您可能需要重构ORM的某些部分。为某些类添加新的、更专业的方法,并使它们使用您手工制作的新查询。然后重构您当前的操作,使其使用这些新方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接