按案例连接选择超过订单的性能

时间:2013-02-12 21:52:21

标签: sql sql-server

我一直在努力解决这个问题,在某些情况下,sql需要花费30多分钟才能在current的100k行的表上执行,而大约10是pending。这是我认为是罪魁祸首的较大连接语句的一部分。基本上,sql的目的是对current行和pending行的副本进行排序,以便所有挂起的行位于顶部或底部。它是变革框架管理的一部分。任何想法如何在一个表现稳定的男性中完成?对于某些情况下的记录,在具有10M行和100个挂起更改的表上,相同的sql在10秒内运行。排序是在计算字段上完成的,这个问题更加复杂。数据库是ms sql server 2008 R2。

更新:我正在添加其余的联接,以表明疯狂有半原因。

此处的唯一目的是获取当前记录和待处理记录的组合,以显示未来表格在批准更改后的样式,排序以便更改显示在顶部或底部(ASC或DSC)在hasPending上,额外的Current2连接是添加一些额外的识别数据。

一般来说,它会做它应该做的事情,相当不错的几秒响应时间,10当达到大约10M记录时,然而在少数情况下,一切都会慢慢地爬行,响应时间达到12-30分钟。

WITH [ResultPage] AS 
SELECT 
    ROW_NUMBER() OVER 
    (ORDER BY 
        CASE WHEN [Current].[ID] IN 
            (SELECT [CID] 
             FROM [Pending] AS p
             INNER JOIN [Current] ON [Current].[ID] like p.[CID] 
             WHERE (p.[User] = 'admin'))
          THEN 1 
          ELSE 0 
       END ASC, 
       [Current].[ID] ASC) AS [RowID], 
    [Current].[ID], 
    CASE WHEN [Current].[ID] IN 
        (SELECT [CID] 
         FROM [Pending] AS p 
     INNER JOIN [Current]  ON [Current].[ID] like p.[CID] 
         WHERE (p.[User] = 'admin'))
       THEN 1 
       ELSE 0 
    END AS [HasPending] 
FROM [Current] 
INNER JOIN [Current2] AS [Table2] ON ([Current].[T2ID] = [Table2].[ID])
SELECT [ResultPage].[RowID], [ResultPage].[HasPending], [Current2].[ID] As [Current2^ID], [Tag].Name], 
etc... etc...
FROM [ResultPage] 
INNER JOIN [Current]  ON ([Current].[ID] = [ResultPage].[ID]) 
 INNER JOIN [Current2] ON ([Current].[T2ID] = [Current2].[ID]) 
 WHERE (([ResultPage].[RowID] BETWEEN -1 AND 50)) ORDER BY [ResultPage].[RowID] ASC

3 个答案:

答案 0 :(得分:2)

我猜有一个双子查询非常昂贵。如果您在单个子查询中确定[hasPending]并保存在某些JOIN上,则效果可能会更好。

SELECT
    [sub].[ID],
    ROW_NUMBER() OVER (ORDER BY [sub].[hasPending] DESC, [sub].[ID] ASC) AS [RowID],
    [sub].[hasPending]
FROM
(
    SELECT
        [Current].[ID],
        (CASE WHEN COUNT([pending].[ID]) > 0 THEN 1 ELSE 0 END) AS [hasPending]
    FROM [Current]
    INNER JOIN [Current2] 
        ON [Current].[T2ID] = [Current2].[ID]
    LEFT JOIN [Pending] 
        ON [Current].[ID] = [Pending].[ID] AND [Pending].[User] = 'Admin'
    GROUP BY [Current].[ID]
) AS [sub]

修改:COUNT(*)更改为COUNT([pending].[ID]),以便正确确定[hasPending]

答案 1 :(得分:1)

尝试一下,这应该加快速度,因为id会被转储到表变量而不必每次循环都要查询。这很可能不是最好的解决方案,但如果没有关于你要做什么的进一步信息,至少应该有所帮助。

declare @ids table
(
    id int
)

insert into @ids(id)
SELECT [ID] From [Pending]
Inner Join [Current] On [Current].[ID] = [Pending].[ID] 
WHERE ([Pending].[User] = 'admin')

SELECT ROW_NUMBER() OVER 
    (ORDER BY Case When [Current].[ID] In (select id from @ids) 
    THEN 1 ELSE 0 END ASC, [Current].[ID] ASC) As [RowID], 
    [Current].[ID], 
    Case When [Current].[ID] In (select id from @ids)
    THEN 1 ELSE 0 END AS [HasPending] 
FROM [Current] 
INNER JOIN [Current2] AS [Table2] ON ([Current].[T2ID] = [Table2].[ID])

如果您的ID是唯一的,我也可以使用它,我认为它们是:

SELECT ROW_NUMBER() OVER 
    (ORDER BY a.haspending, a.[ID] ASC) As [RowID],
    a.id, a.haspending,
from (select [Current].[ID], 
      Case when a.id is not null THEN 1 ELSE 0 END [HasPending] 
        FROM [Current] 
        INNER JOIN [Current2] AS [Table2] ON ([Current].[T2ID] = [Table2].[ID])
        left join  (SELECT distinct [ID] From [Pending]
                    Inner Join [Current] On [Current].[ID] = [Pending].[ID] 
                    WHERE ([Pending].[User] = 'admin')) a on a.id = [Current].[ID]) a

答案 2 :(得分:0)

好吧,在Jacco建议的帮助下,修改它以给出正确的结果,我能够让它运行起来,将查询减少到令人惊讶的1秒...

WITH [ResultPage] AS 
(SELECT
    sub.id as id,
    ROW_NUMBER() OVER (ORDER BY [sub].[hasPending] DESC, [sub].[ID] ASC) AS [RowID],
    [sub].[hasPending]
 FROM
(
SELECT
    a.[ID],
    (CASE WHEN p.[CID] is not null THEN 1 ELSE 0 END) AS [hasPending]
FROM [Alarm] a

full outer JOIN [Pending] as p
    ON a.[ID] like p.[CID] 
GROUP BY a.[ID],p.[CID]
) AS [sub]
INNER JOIN [Current2] ON (sub.[T2ID] = [Current2].[ID]))
SELECT [ResultPage].[RowID], [ResultPage].[HasPending], [Current2].[ID] As [Current2^ID],
etc...etc...
 FROM [ResultPage] 
INNER JOIN [Current] ON ([Current].[ID] = [ResultPage].[ID]) 
INNER JOIN [Current2] ON ([Current].[T2ID] = [Current2].[ID]) 
WHERE (([ResultPage].[RowID] BETWEEN -1 AND 50)) ORDER BY [ResultPage].[RowID] ASC