trying to reduce the amount of logical reads

  • I am using sql2008 on a virtual env. I have a very simple query that has long durations that I think is due to an excessive amount of logical reads (211938). The table has about 2.1 million rows. I have indexes in place (DTA didn't have anything to add) and nolock. Any ideas?

    SELECT max(id)

    from dbo.table WITH (NOLOCK)

    where field_name1 = 'DOWNLOAD'

    and field_name2 = 'XYZ'

    There is an exception to every rule, except this one...

  • See - http://sqlblog.com/blogs/andrew_kelly/archive/2009/04/10/how-dirty-are-your-reads.aspx

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • Please post index definitions.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • I'm guessing this is a local db on a slow disk subsystem so if you have GBs of data to read then yes this will take a long time.

    Without seeing the execution plan, the only thing I can offer at this point is to try this which I've seen beat max on a test a long time ago :

    SELECT TOP 1

    ID

    from

    dbo.tbl WITH ( NOLOCK )

    where

    field_name1 = 'DOWNLOAD'

    and field_name2 = 'XYZ'

    ORDER BY ID DESC

    Here's why to avoid nolock : http://sqlblog.com/blogs/andrew_kelly/archive/2009/04/10/how-dirty-are-your-reads.aspx

  • The id field I'm getting the max from is not the primary clustered index, it is just another column (ID).

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON PRIMARY

    GO

    CREATE NONCLUSTERED INDEX [N3] ON [dbo].table

    (

    ID ASC,

    OTHER_ID ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON PRIMARY

    GO

    There is an exception to every rule, except this one...

  • From that info, the server likely has to scan the whole table.

    Include the id you need to select in the N2 index (included column). as the third key.

    Edited brain fart. You guys have a good week-end!

  • Ninja's_RGR'us (8/11/2011)


    I'm guessing this is a local db on a slow disk subsystem so if you have GBs of data to read then yes this will take a long time.

    Without seeing the execution plan, the only thing I can offer at this point is to try this which I've seen beat max on a test a long time ago :

    SELECT TOP 1

    ID

    from

    dbo.tbl WITH ( NOLOCK )

    where

    field_name1 = 'DOWNLOAD'

    and field_name2 = 'XYZ'

    ORDER BY ID DESC

    Here's why to avoid nolock : http://sqlblog.com/blogs/andrew_kelly/archive/2009/04/10/how-dirty-are-your-reads.aspx

    The reads remained equal. Below are results from SET STATISTICS IO, time ON using both methods. The first result is my original. I will check into the dirty reads article. Thanks.

    SQL Server parse and compile time:

    CPU time = 0 ms, elapsed time = 0 ms.

    SQL Server Execution Times:

    CPU time = 0 ms, elapsed time = 0 ms.

    SQL Server parse and compile time:

    CPU time = 0 ms, elapsed time = 0 ms.

    (1 row(s) affected)

    Table 'table'. Scan count 1, logical reads 211930, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:

    CPU time = 282 ms, elapsed time = 275 ms.

    (1 row(s) affected)

    Table 'table'. Scan count 1, logical reads 211930, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

    SQL Server Execution Times:

    CPU time = 296 ms, elapsed time = 296 ms.

    SQL Server Execution Times:

    CPU time = 578 ms, elapsed time = 572 ms.

    (1 row(s) affected)

    SQL Server Execution Times:

    CPU time = 0 ms, elapsed time = 0 ms.

    There is an exception to every rule, except this one...

  • Thanks for the update. And with the extra index?

    BTW, if you don't post the actual execution plan we're just guessing at this... which we don't like to do ;-).

  • Comments withdrawn. Gail's example below is a lot more clear and concise than all my verbage.

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Add ID as a 3rd key column to this index:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC

    )

    In other words, change it to this:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC,

    ID

    )

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • GilaMonster (8/11/2011)


    Add ID as a 3rd key column to this index:

    Out of curiousity, why not include the ID instead of key it? Would reduce the tree load.


    - Craig Farrell

    Never stop learning, even if it hurts. Ego bruises are practically mandatory as you learn unless you've never risked enough to make a mistake.

    For better assistance in answering your questions[/url] | Forum Netiquette
    For index/tuning help, follow these directions.[/url] |Tally Tables[/url]

    Twitter: @AnyWayDBA

  • If the ID is included as part of the index, the optimizer can find MAX by matching on [field_name1] and [field_name2], then reading the last value of ID. There are pointers in the index going both forwards and backwards so this is basically one read after [field_name1] and [field_name2] are found. AND this one read is not being done at the leaf level.

    If you make it an included column, then it has to scan all leaves match for [field_name1] and [field_name2] from start to finish. This could be inconsequential or it could involve many, many pages having to be read to perform the scan.

    Basically, including it as an indexed column can take away a lot of the I/O for this particular query.

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • GilaMonster (8/11/2011)


    Add ID as a 3rd key column to this index:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC

    )

    In other words, change it to this:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC,

    ID

    )

    That's what I would've guessed, but the DAT didn't recommend it so I didn't do it. I will try that tomorrow thanks!

    There is an exception to every rule, except this one...

  • Evil Kraig F (8/11/2011)


    GilaMonster (8/11/2011)


    Add ID as a 3rd key column to this index:

    Out of curiousity, why not include the ID instead of key it? Would reduce the tree load.

    I'm 'glad' I'm not the only one who had that brain fart today. My default mode when editing an index is to use the include option to reduce the increase of the load I put on that index (and since I do olap I <never> have to get only 1 value).

    The only thing is that in this case, sorting actually improves the query even more (top / max)...

    P.S. My trick of top 1 vs max was tested back in 2000. I'm 95% sure that was changed in 2k5+ where it produces the same plan. Since I'm off for the we I'll leave it at that.

  • SQLHeap (8/11/2011)


    GilaMonster (8/11/2011)


    Add ID as a 3rd key column to this index:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC

    )

    In other words, change it to this:

    CREATE NONCLUSTERED INDEX [N2] ON [dbo].table

    (

    field_name2 ASC,

    field_name1 ASC,

    ID

    )

    That's what I would've guessed, but the DAT didn't recommend it so I didn't do it. I will try that tomorrow thanks!

    DAT DTA is IM<NS>HO a very dangerous tool. Especially if you don't know what you are doing. And when you know what you are doing you don't need that tool. Yes I know there's a catch 22 somewhere in there.

    Please read this to rid yourself of that limitation : http://www.sqlservercentral.com/articles/books/65831/

Viewing 15 posts - 1 through 15 (of 20 total)

You must be logged in to reply to this topic. Login to reply