0

我已经为此苦苦挣扎了一段时间,在某些情况下,下面的 sql 需要超过 30 分钟才能在包含 100k 行current且大约 10行的表上执行pending。这是我已确定为罪魁祸首的更大连接语句的一部分。基本上,sql 的目的是对行的连接和current行的副本进行排序,pending以便所有待处理的行都位于顶部或底部。它是变革管理框架的一部分。有什么想法可以以始终如一的良好表现的方式完成吗?作为记录,在某些情况下,相同的 sql 在具有 10M 行和 100 条待处理更改的表上运行时间不到 10 秒。排序是在计算字段上完成的这一事实使问题更加复杂。数据库是 ms sql server 2008 R2。

更新:我正在添加其余的连接以表明这种疯狂是有原因的。

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

通常它会做它应该做的事情,相当不错的几秒钟的响应时间,当达到大约 1000 万条记录时为 10 秒,但是在少数情况下,一切都一直缓慢到爬行,响应时间高达 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
4

3 回答 3

2

我想有一个双子查询是相当昂贵的。如果您[hasPending]在单个子查询中确定 并保存在某些JOIN's 上,它可能会执行得更好。

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]正确确定。

于 2013-02-12T23:17:46.233 回答
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
于 2013-02-12T22:26:09.533 回答
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
于 2013-02-13T03:32:40.040 回答