优化此SQL查询

时间:2010-02-02 09:59:26

标签: sql sql-server

我有这个SQL查询,但运行缓慢,

SELECT 
    wr.wr_re_id as ReID, 
    sum(wr.wr_total) as PRTotal 
FROM 
    Workorder2 w
    INNER JOIN 
    Workorder_Row2 wr ON wr.wr_wo_id = w.wo_id
WHERE 
    (w.wo_type = 1 or w.wo_type = 2)
    AND wr.wr_row_type = 2
    AND w.wo_lo_id like '%'
    AND w.wo_date_time >= '2010-01-01' 
    AND w.wo_date_time <= '2010-01-31'
    AND wr.wr_wo_id IN
        (SELECT 
            wr2.wr_wo_id 
        FROM 
            Workorder_Row2 wr2 
            INNER JOIN Workorder2 w2 ON w2.wo_id = wr2.wr_wo_id 
            AND w2.wo_date_time >= '2010-01-01' 
            AND w2.wo_date_time <= '2010-01-31' 
        WHERE 
            wr2.wr_row_type = 1)
GROUP BY 
    wr.wr_re_id

有什么建议我可以加快速度吗?执行时间差不多1分钟 我认为问题出在AND wr.wr_wo_id IN (SELECT ...上,但我需要知道是否存在包含威胁的同一工作单上的产品销售。

3 个答案:

答案 0 :(得分:2)

首先,看看你的执行计划。由于我们不了解您的数据,因此我们很难对其进行优化。

跳出最多的是wr.wr_wo_id IN (SELECT...)部分。这将是一个更有效的连接,如下所示:

SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal 
FROM Workorder2 w
    INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
    INNER JOIN (
        SELECT DISTINCT wr2.wr_wo_id
        FROM Workorder_Row2 wr2 
            INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id 
        WHERE w2.wo_date_time >= '2010-01-01' 
            AND w2.wo_date_time <= '2010-01-31'
            AND wr2.wr_row_type = 1
    ) T ON T.wr_wo_id = wr.wr_wo_id
WHERE (w.wo_type = 1 or w.wo_type = 2)
    AND wr.wr_row_type = 2
    AND w.wo_lo_id like '%'
    AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
GROUP BY wr.wr_re_id

值得考虑是否有助于增加指数。这取决于您更新/插入/删除这些表的频率,以及每列的选择性。

附加:

要反过来,即替换WHERE wr.wr_wo_id NOT IN (SELECT...),您可以使用:

SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal 
FROM Workorder2 w
    INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
    LEFT JOIN (
        SELECT DISTINCT wr2.wr_wo_id
        FROM Workorder_Row2 wr2 
            INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id 
        WHERE w2.wo_date_time >= '2010-01-01' 
            AND w2.wo_date_time <= '2010-01-31'
            AND wr2.wr_row_type = 1
    ) T ON T.wr_wo_id = wr.wr_wo_id
WHERE T.wr2.wr_wo_id IS NULL
    AND (w.wo_type = 1 or w.wo_type = 2)
    AND wr.wr_row_type = 2
    AND w.wo_lo_id like '%'
    AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
GROUP BY wr.wr_re_id

然而,它更具可读性(我猜,虽然尝试它)使用效率更高:

SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal 
FROM Workorder2 w
    INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
WHERE (w.wo_type = 1 or w.wo_type = 2)
    AND wr.wr_row_type = 2
    AND w.wo_lo_id like '%'
    AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
    AND NOT EXISTS (
        SELECT NULL
        FROM Workorder_Row2 wr2 
            INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id 
        WHERE w2.wo_date_time >= '2010-01-01' 
            AND w2.wo_date_time <= '2010-01-31'
            AND wr2.wr_row_type = 1
            AND wr2.wr_wo_id = wr.wr_wo_id
    )
GROUP BY wr.wr_re_id

答案 1 :(得分:1)

如果您使用的是MySQL,则可以使用EXPLAIN来了解查询速度慢的原因。有关EXPLAIN语法的详细信息,请参阅http://dev.mysql.com/doc/refman/5.1/en/explain.html

答案 2 :(得分:0)

每个SQL数据库引擎都有一个查询分析器,可以帮助您找出运行缓慢的原因。但在这种情况下,解决方案可能就像在这些列上创建索引一样简单:

  • Workorder2.wo_id
  • Workorder_Row2.wr_wo_id

尝试将这些索引添加为聚簇索引。如果这不起作用,请查询查询分析器以获取更多想法。

  • 在SQL Server中,通过在查询窗口中输入查询并单击“显示估计执行计划”和“在数据库调优顾问中分析查询”按钮,可以在Management Studio中找到它。
  • 在MySQL中,您可以使用EXPLAIN命令

注意:不要担心“IN(SELECT ...)”部分。它将与任何现代数据库引擎上的连接一样高效。