简体   繁体   中英

SQL Server query optimisation

I inherited this hellish query designed for pagination in SQL Server.

It's only getting 25 records, but according to SQL Profiler, it does 8091 reads, 208 writes and takes 74 milliseconds. Would prefer it to be a bit faster. There is an index on the ORDER BY column deployDate .

Anyone have any ideas on how to optimise it?

SELECT TOP 25 
    textObjectPK, textObjectID, title, articleCredit, mediaCredit,
    commentingAllowed,deployDate, 
    container, mediaID, mediaAlign, fileName AS fileName, fileName_wide AS fileName_wide, 
    width AS width, height AS height,title AS mediaTitle, extension AS extension, 
    embedCode AS embedCode, jsArgs as jsArgs, description as description, commentThreadID,
    totalRows = Count(*) OVER()
 FROM
    (SELECT 
        ROW_NUMBER() OVER (ORDER BY textObjects.deployDate DESC) AS RowNumber,
        textObjects.textObjectPK, textObjects.textObjectID, textObjects.title,  
        textObjects.commentingAllowed, textObjects.credit AS articleCredit, 
        textObjects.deployDate, 
        containers.container, containers.mediaID, containers.mediaAlign, 
        media.fileName AS fileName, media.fileName_wide AS fileName_wide, 
        media.width AS width, media.height AS height, media.credit AS mediaCredit, 
        media.title AS mediaTitle, media.extension AS extension, 
        mediaTypes.embedCode AS embedCode, media.jsArgs as jsArgs, 
        media.description as description, commentThreadID,
        TotalRows = COUNT(*) OVER ()
     FROM textObjects WITH (NOLOCK) 
     INNER JOIN containers WITH (NOLOCK) 
                ON containers.textObjectPK = textObjects.textObjectPK 
                AND (containers.containerOrder = 0 or containers.containerOrder = 1)
     INNER JOIN LUTextObjectTextObjectGroup tog WITH (NOLOCK)
                ON textObjects.textObjectPK = tog.textObjectPK
                AND tog.textObjectGroupID in (3)
     LEFT OUTER JOIN media WITH (NOLOCK) 
                ON containers.mediaID = media.mediaID 
     LEFT OUTER JOIN mediaTypes WITH (NOLOCK) 
                ON media.mediaTypeID = mediaTypes.mediaTypeID
     WHERE (((version = 1)   
              AND (textObjects.textObjectTypeID in (6))  
       AND (DATEDIFF(minute, deployDate, GETDATE()) >= 0) 
       AND (DATEDIFF(minute, expireDate, GETDATE()) <= 0))
       OR  ( (version = 1) AND (textObjects.textObjectTypeID in (6))  
       AND (DATEDIFF(minute, deployDate, GETDATE()) >= 0) 
       AND (expireDate IS NULL))) 
       AND deployEnglish = 1
       ) tmpInlineView
  WHERE RowNumber >= 51
  ORDER BY deployDate DESC 

I am in a similar position to with the same sort of queries. Here are some tips:

  • Look at the query plans to make sure you have the right indexes.
  • I'm not sure if MSSQL optimizes around DATEDIFF(), but if it doesn't you can precompute threshold dates and turn it into a BETWEEN clause.
  • If you don't need to order by all those columns in your ROW_NUMBER() clause, get rid of them. That may allow you to do the pagination on a much simpler query, then just grab the extra data you need for the 25 rows you are returning.

Also, rewrite the two LEFT OUTER JOINs like this:

LEFT OUTER JOIN 
(
    media WITH (NOLOCK) 
        LEFT OUTER JOIN mediaTypes WITH (NOLOCK) 
             ON media.mediaTypeID = mediaTypes.mediaTypeID
)
    ON containers.mediaID = media.mediaID 

which should make the query optimizer behave a little better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM