0

私はしばらくの間これに取り組んできました。場合によっては、以下のsqlは100k行のテーブルで実行するのに30分以上かかりcurrent、約10はpendingです。これは、私が犯人であると特定した、より大きな結合ステートメントの一部です。基本的に、SQLの目的は、行の結合とcurrent行のコピーを並べ替えて、pending保留中のすべての行が上または下になるようにすることです。これは、変更フレームワークの管理の一部です。一貫してうまく機能するマナーでこれをどのように行うことができるかについてのアイデアはありますか?レコードの場合、同じSQLが、1,000万行と数百の保留中の変更があるテーブルで10秒未満で実行される場合があります。問題は、計算されたフィールドでソートが行われるという事実によって悪化します。データベースはmssqlserver2008R2です。

更新:狂気に半理由があることを示すために、残りの結合を追加しています。

繰り返しますが、これの唯一の目的は、現在のレコードと保留中のレコードの組み合わせを取得し、変更が承認され、変更が上部または下部に表示されるように並べ替えられた後の将来のテーブルがどのようになるかを示すことです(hasPendingのASCまたはDSC) )、追加のCurrent2結合は、いくつかの追加の識別データを追加することです。

一般に、それは本来の動作を実行します。応答時間は数秒で、約1,000万レコードに達すると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

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 に答える