Can't understand why I'm getting index scans

  • I have this simple query:

    SELECT Count('x') FROM PayeeMaster PM

    INNER JOIN PayeeLink PL (nolock) ON PM.PayeeID = PL.PayeeID

    that results in an index scan (i tried to attach plan but being blocked)

    I have a clustered index for both tables that has all fields, but yet I still get an index scan and not a 'seek'....

    Guessing it has something to do with the Primary keys, since it shows in the Execution plan as using the PK_. How can I get it to do an index seek and keep my existing primary keys?

  • you are asking for a count to be returned, that cannot be done by a seek. the smallest index will be scanned to return the count value.

    ---------------------------------------------------------------------

  • thank you

  • anway to get the count in the above query without using 'count'?

  • SELECT

    OBJECT_NAME(object_id) AS ObjectName

    , object_id

    , SUM(rows) AS rows

    , SUM(data_pages) data_pages

    , CONVERT(DECIMAL(18,2), SUM(data_pages) * 8.0 / 1024 / 1024) GBs

    FROM

    sys.partitions p

    INNER JOIN sys.allocation_units a

    ON p.partition_id = a.container_id

    WHERE

    index_id IN (0, 1)

    GROUP BY

    object_id

    HAVING

    SUM(rows) > 0

  • One way would be to hi the sys.partitions table. Here's an example of a query that returns row counts for every table in the msdb database. You could take this and easily tweak it for your needs by changing what db it's pointing to, and possibly adding a where clause on the table name.

    select

    sum (spart.rows) as CntOfRows,

    t.name

    FROM msdb.sys.partitions spart

    inner join msdb.sys.tables t on spart.object_id = t.object_id

    where spart.index_id < 2

    group by t.name

    order by CntOfRows desc



    A.J.
    DBA with an attitude

  • if you are just after a rowcount then

    sp_spaceused after a dbcc updateusage,

    rowcnt in sysindexes where indid = 0 or 1,

    a max value if you know you have consecutively increasing value with no gaps

    ---------------------------------------------------------------------

  • I'm having trouble with the syntax when I try to add this to my query:

    SELECT Count('x') FROM PayeeMaster PM

    INNER JOIN PayeeLink PL ON PM.PayeeID = PL.PayeeID

    INNER JOIN PaymentParent PP (nolock) ON PL.UserID = PP.UserID AND PL.PayeeRefNo = PP.PayeeRefNo

    INNER JOIN PaymentChild PC (nolock) ON PP.UserID = PC.UserID AND PP.PaymentRefNo = PC.PaymentRefNo

    INNER JOIN AccountProfile Acct (nolock) ON PP.UserID = Acct.UserID AND PP.AccountRefNo = Acct.AccountRefNo

  • sys.partitions is a count of all rows in the table, nothing more.

    If you want to count rows of a query, use count(*) (count('x') just looks silly). It will be index scans, you're asking SQL to read the entire of every table, the most efficient way to do that is to scan it. A seek on every single row of the table is blithering stupid, SQL will not do that, it knows better. (a seek on every row would require 2-3 page reads per row, whereas a scan requires one read per page)

    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
  • krypto69 (7/19/2011)


    I'm having trouble with the syntax when I try to add this to my query:

    SELECT Count('x') FROM PayeeMaster PM

    INNER JOIN PayeeLink PL ON PM.PayeeID = PL.PayeeID

    INNER JOIN PaymentParent PP (nolock) ON PL.UserID = PP.UserID AND PL.PayeeRefNo = PP.PayeeRefNo

    INNER JOIN PaymentChild PC (nolock) ON PP.UserID = PC.UserID AND PP.PaymentRefNo = PC.PaymentRefNo

    INNER JOIN AccountProfile Acct (nolock) ON PP.UserID = Acct.UserID AND PP.AccountRefNo = Acct.AccountRefNo

    No other way than count(*) for this scenario.

  • I'm pretty sure we told you already but you really need to read this and THEN decide if you risk using nolock.

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

  • okay thanks everyone

    good karma to you all thanks for taking the time top answer..

  • yeah I know...I've talked to the devs about no lock...

    they stopped using it, and I remove it where/when I see it...

  • my dev just emailed me back and said that if I look at this query it uses 'SEEK' not scan and he;s right!!

    what the hell?

    SELECT Count('x') FROM PayeeMaster PM

    INNER JOIN PayeeLink PL (nolock) ON PM.PayeeID = PL.PayeeID

    Where userid='10041'

    above results in seek

    SELECT Count('x') FROM PayeeMaster PM

    INNER JOIN PayeeLink PL (nolock) ON PM.PayeeID = PL.PayeeID

    above results in scan

  • It's not the same query.

    The first one filters out more rows. While doing the seek, it can also count.

    Also the estimated # of rows returned must be really low (% of whole table) for the seek to be used as the plan.

    http://sqlinthewild.co.za/index.php/2009/01/09/seek-or-scan/

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

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