views:

44

answers:

1

Dear all,

I am currently upgrading a database server from SQL Server 2000 to SQL Server 2008 R2. One of my queries used to take under a second to run and now takes in excess of 3 minutes (running on faster a faster machine).

I think I have located where it is going wrong but not why it is going wrong. Could somebody explain what the problem is and how I might resolve it?

The abridged code is as follows:

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
  )

I believe the issue is located on the "txn.transactionid IS NULL OR" line. If I remove this condition it runs as fast as it used to (less than a second) and returns all the records minus the 3 rows that that statement would have included. If I remove the second part of the OR statement it returns the 3 rows that I would expect in less than a second.

Could anybody point me in the correct direction as to why this is happening and when this change occured?

Many thanks in advance

Jonathan


I have accepted Alex's solution and included the new version of the code. It seems that we have found 0.1% of queries that the new query optimiser runs slower.

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
+3  A: 

Try restructuring the query using a CTE and 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
Alex Whittles