SQL查询优化帮助

Posted

技术标签:

【中文标题】SQL查询优化帮助【英文标题】:SQL query Optimization help 【发布时间】:2011-07-07 01:29:28 【问题描述】:

我有以下 SQL 查询

Declare @tempcalctbl Table
(
    ItemId varchar(50),
    ItemLocation varchar(50),
    ItemNo varchar(50),
    Width real,
    Unit varchar(50),
    date datetime
)

Insert Into @tempcalctbl 
     Select distinct SubId,ItemLocation,ItemNo,
       (ABS((Select width From @temptbl a Where ItemProcess ='P1'and a.ItemId = c.ItemId 
           and a.ItemNo = c.ItemNo and a.ItemLocation = c.ItemLocation)
       -(Select width From @temptbl b Where ItemProcess ='P2' and b.ItemId = c.ItemId 
           and b.ItemNo = c.ItemNo and b.ItemLocation = c.ItemLocation))) * 1000,
       Unit,date
From @temptbl c
Group by ItemId,ItemLocation,ItemNo,Unit,date

我想知道如何优化这个查询。 这个想法是根据相同的ItemID,相同的ItemNo和相同的ItemLocation找出ItemProcess'P1'和'P2'之间的宽度差异(p1's item - p2's item)。 我有大约 75000 个,花了超过 25 分钟才得到所有 ItemId 的宽度差异。

我尝试使用 Group by 进行宽度不同的计算,但它会返回多行而不是返回错误的值。顺便说一句,我使用的是 MS SQL Server 2008,@tempcalctbl 是我在存储过程中声明的表。

【问题讨论】:

您是否只是想获取特定 productID 的最大和最小宽度之间的差异? 您可以通过只对@temptbl 执行一次来更快地获得这部分查询,但是我怀疑转储到@temptbl 然后级联到另一个@table 变量的整个过程应该是进行了调查。为什么你认为只有这部分查询需要 25 分钟?您是否为@temptbl 的初始填充(以及首先完成的任何其他工作)计时? @Brian Hoover 我正在尝试获得与所有 ItemID 不同的宽度。 @Aaron Ya 我确实对@temptbl 的初始人口进行了计时。我单独运行 sql 代码示例运行 @temptbl 的初始填充等。 【参考方案1】:

以下有帮助吗?

INSERT  INTO @tempcalctbl
SELECT  P1.SubId ,
        P1.ItemLocation ,
        P1.ItemNo ,
        ABS(P1.Width - P2.Width) * 1000 AS Width ,
        P1.Unit ,
        P1.date
FROM    @temptbl AS P1
        INNER JOIN @temptbl AS P2 ON P1.ItemId = P2.ItemId
                                     AND P1.ItemNo = P2.ItemNo
                                     AND P1.ItemLocation = P2.ItemLocation
WHERE   P1.ItemProcess = 'P1'
        AND P2.ItemProcess = 'P2'

编辑

要使用索引,您需要将表变量更改为临时表

CREATE TABLE #temptbl
(
    ItemId varchar(50),
    ItemLocation varchar(50),
    ItemNo varchar(50),
    Width real,
    Unit varchar(50),
    date DATETIME,
    ItemProcess INT,
    SubId INT
)

CREATE NONCLUSTERED INDEX Index01 ON #temptbl
(
    ItemProcess ASC,
    ItemId ASC,
    ItemLocation ASC,
    ItemNo ASC
)
INCLUDE ( SubId,Width,Unit,date)
GO

这应该会加快你的速度。

【讨论】:

你为什么放弃GROUP BY 我假设他对每个 Item,ItemNo,Location 组合都有两行,他对我的分组意味着他希望通过忽略 ItemProcess 列来为他们两个都设置一行。在这种情况下,只需选择其中一行“P1”并加入另一行“P2”。应该是相同的结果,但是桌子被击中两次而不是三次。向临时表添加索引将加快速度,并且几乎可以立即完成。但是在我建议一些索引之前,需要先确保我的假设是正确的。 @John Petrak 尝试了您的查询并直观地比较了结果,它可以工作并且时间更短。让我解释得更清楚一点,我想找出相同Item,相同itemNo相同位置的宽度差异。所有项目共享相同的 SubID,但具有多个 ItemNo 和 ItemLocation。例如 subID abc123 可能有 ItemLocation(a,b,c) 和 ItemNo(1,2,3,4,5,6....)。是的,我只需要选择 ItemProcess 'P1' 和 ItemProcess 'P2' 的宽度之一,这两者都会给我不同的宽度。介意告诉我有关索引的信息吗? 用索引信息更新了答案。【参考方案2】:

John Petrak 的回答是本案的最佳查询。 如果现在速度仍然可以接受,也许您可​​以将@temptbl 存储在一个临时的真实表中,并在这四列上创建相关索引。

【讨论】:

以上是关于SQL查询优化帮助的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助来优化 ORACLE SQL 查询 [关闭]

需要帮助优化外连接 SQL 查询

需要帮助优化 SQL 查询

请帮助优化查询

需要帮助优化 T-SQL 查询

SQL Server / T-SQL:查询优化帮助