1

現在、データベース サーバーを SQL Server 2000 から SQL Server 2008 R2 にアップグレードしています。以前は実行に 1 秒もかからなかったクエリの 1 つが、今では 3 分以上かかります (より高速なマシンで実行すると)。

どこがうまくいかないかは突き止めたと思いますが、なぜうまくいかないのかはわかりません。誰かが問題の内容と、それを解決する方法を説明できますか?

要約されたコードは次のとおりです。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

...

FROM 
   Registrar reg
   JOIN EnabledType et ON et.enabledTypeCode = reg.enabled
   LEFT JOIN [Transaction] txn ON txn.registrarId = reg.registrarId
WHERE     
   txn.transactionid IS NULL OR
   txn.transactionid IN
  (
  SELECT MAX(transactionid)
  FROM [Transaction]
  GROUP BY registrarid
  )

問題は「txn.transactionid IS NULL OR」行にあると思います。この条件を削除すると、以前と同じくらい速く (1 秒未満) 実行され、すべてのレコードからそのステートメントに含まれる 3 行を差し引いたものが返されます。OR ステートメントの 2 番目の部分を削除すると、予想される 3 行が 1 秒以内に返されます。

なぜこれが起こっているのか、そしてこの変化がいつ起こったのかについて、誰かが私を正しい方向に向けることができますか?

よろしくお願いします

ジョナサン


私は Alex の解決策を受け入れ、新しいバージョンのコードを含めました。新しいクエリ オプティマイザーの実行が遅くなるクエリが 0.1% 見つかったようです。

WITH txn AS ( 
    SELECT registrarId, balance , ROW_NUMBER() OVER (PARTITION BY registrarid ORDER BY transactionid DESC) AS RowNum 
    FROM [Transaction] 
) 
SELECT 
    reg.registrarId,
    reg.ianaId, 
    reg.registrarName, 
    reg.clientId,
    reg.enabled,
    ISNULL(txn.balance, 0.00) AS [balance],
    reg.alertBalance,
    reg.disableBalance,
    et.enabledTypeName
FROM 
    Registrar reg
    JOIN EnabledType et
        ON et.enabledTypeCode = reg.enabled
    LEFT JOIN txn
        ON txn.registrarId = reg.registrarId
WHERE
    ISNULL(txn.RowNum,1)=1 
ORDER BY 
    registrarName ASC
4

1 に答える 1

3

CTE と ROW_NUMBER を使用してクエリを再構築してみてください...

WITH txn AS (
    SELECT registrarId, transactionid, ...
        , ROW_NUMBER() OVER (PARTITION BY registrarid ORDER BY transactionid DESC) AS RowNum
    FROM [Transaction]
)
SELECT 
    ...
FROM  
   Registrar reg 
   JOIN EnabledType et ON et.enabledTypeCode = reg.enabled 
   LEFT JOIN txn ON txn.registrarId = reg.registrarId 
        AND txn.RowNum=1
于 2010-10-27T16:24:58.220 に答える