Fastest way to count total number of rows...

  • Hi,

    What's the best way of doing a complete row count on a table?

    SELECT COUNT(*) FROM MovimentosFuncionarios

    SELECT SUM(SP.rows) AS [total_rows]

    FROM sys.partitions SP

    WHERE SP.object_id = OBJECT_ID('MovimentosFuncionarios') AND SP.[index_id] = 1

    is the sys.partitions table always "reliable" as for the number of rows?

    Thanks,

    Pedro



    If you need to work better, try working less...

  • PiMané (1/31/2013)


    is the sys.partitions table always "reliable" as for the number of rows?

    It's reliable as an approximate count for an individual table or index. You may be able to get more accurate results by running "DBCC UPDATEUSAGE" with the COUNT_ROWS option just before querying.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • I'm trying to determine the fastest way, and as far as I tested, the sys.partitions is the fastest but just don't know how reliable the info is...

    DBCC UPDATEUSAGE is even slower than SELECT COUNT(*)....

    Pedro



    If you need to work better, try working less...

  • PiMané (1/31/2013)


    I'm trying to determine the fastest way, and as far as I tested, the sys.partitions is the fastest but just don't know how reliable the info is...

    DBCC UPDATEUSAGE is even slower than SELECT COUNT(*)....

    Pedro

    As I said, it's an approximate row count so when used as such it is very reliable. If you're asking whether or not it will ever not be accurate, then yes it will sometimes be different to the actual row count. I mentioned DBCC UPDATEUSAGE because it corrects row count inaccuracies in the catalog views.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • This is the fastest and most reliable way I have found.

    SELECT SUM (row_count)

    FROM sys.dm_db_partition_stats

    WHERE object_id = OBJECT_ID('dbo.MovimentosFuncionarios')

    AND (index_id=0 or index_id=1);

    Enjoy!

  • Thanks,

    Pedro



    If you need to work better, try working less...

  • Dave62 (1/31/2013)


    This is the fastest and most reliable way I have found.

    SELECT SUM (row_count)

    FROM sys.dm_db_partition_stats

    WHERE object_id = OBJECT_ID('dbo.MovimentosFuncionarios')

    AND (index_id=0 or index_id=1);

    Enjoy!

    Still an approximate row count.

    dm_db_partition_stats

    sys.partitions


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • i thought you had to get the actual counts from sys.indexes; since the index must have a heap/PK index for every table, teh row counts are materialized exactly correct there:

    SELECT so.[name] as

    , CASE WHEN si.indid between 1 and 254

    THEN si.[name] ELSE NULL END

    AS [Index Name]

    , si.indid, rows

    FROM sys.sysindexes si

    INNER JOIN sysobjects so

    ON si.id = so.id

    WHERE si.indid < 2

    AND so.type = 'U' -- Only User Tables

    AND so.[name] != 'dtproperties'

    ORDER BY so.[name]

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!

  • Lowell (1/31/2013)


    i thought you had to get the actual counts from sys.indexes; since the index must have a heap/PK index for every table, teh row counts are materialized exactly correct there:

    No, they're not.

    sysindexes is deprecated, as is sysobjects, will be removed, should not be used. sys.indexes does not have a row count. sysindexes row count is known to be inaccurate, potentially very inaccurate. sys.partitions should be transactionally correct. Should.

    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
  • Lowell (1/31/2013)


    i thought you had to get the actual counts from sys.indexes; since the index must have a heap/PK index for every table, teh row counts are materialized exactly correct there:

    SELECT so.[name] as

    , CASE WHEN si.indid between 1 and 254

    THEN si.[name] ELSE NULL END

    AS [Index Name]

    , si.indid, rows

    FROM sys.sysindexes si

    INNER JOIN sysobjects so

    ON si.id = so.id

    WHERE si.indid < 2

    AND so.type = 'U' -- Only User Tables

    AND so.[name] != 'dtproperties'

    ORDER BY so.[name]

    The sysindexes table may not be as reliable because the accuracy will be determined by when the statistics have been updated. In addition, Microsoft says sysindexes will be removed in future versions.

    MSDN sysindexes

  • Lowell (1/31/2013)


    i thought you had to get the actual counts from sys.indexes; since the index must have a heap/PK index for every table, teh row counts are materialized exactly correct there:

    SELECT so.[name] as

    , CASE WHEN si.indid between 1 and 254

    THEN si.[name] ELSE NULL END

    AS [Index Name]

    , si.indid, rows

    FROM sys.sysindexes si

    INNER JOIN sysobjects so

    ON si.id = so.id

    WHERE si.indid < 2

    AND so.type = 'U' -- Only User Tables

    AND so.[name] != 'dtproperties'

    ORDER BY so.[name]

    You've written down sys.indexes (which doesn't have a row count) then queries sys.sysindexes (which is deprecated).

    I'm fairly sure that the only way to guarantee an accurate count is to directly query the table. The catalog and dynamic management views are normally correct, but not guaranteed - they're documented as "approximate" counts.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Dave62 (1/31/2013)


    The sysindexes table may not be as reliable because the accuracy will be determined by when the statistics have been updated.

    The row count in sysindexes is not related to statistics updates.

    CREATE DATABASE testingindexes

    GO

    ALTER DATABASE testingindexes SET AUTO_CREATE_STATISTICS OFF

    ALTER DATABASE testingindexes SET AUTO_UPDATE_STATISTICS OFF

    GO

    USE testingindexes

    GO

    CREATE TABLE useless (number int)

    INSERT INTO useless

    SELECT object_id + column_id FROM msdb.sys.columns AS c

    GO

    SELECT * FROM sys.stats AS s WHERE object_id = OBJECT_ID('useless') -- no rows, no statistics created or updated on that table

    SELECT * FROM sysindexes WHERE id = OBJECT_ID('useless') -- rowcount of 2103

    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 (1/31/2013)


    The row count in sysindexes is not related to statistics updates.

    This quote from the MSDN page I referenced seems to indicate some relation.

    "Counts the total number of inserted, deleted, or updated rows since the last time statistics were updated for the table."

  • Won't this work (slightly different than what's posted)? - can't say I've ever noticed a count not equaling a select COUNT on a table directlySELECT ps.row_count

    FROM sys.indexes AS i

    INNER JOIN sys.objects AS o ON

    i.OBJECT_ID = o.OBJECT_ID

    INNER JOIN sys.dm_db_partition_stats AS ps ON

    i.OBJECT_ID = ps.OBJECT_ID

    AND i.index_id = ps.index_id

    WHERE

    i.index_id < 2

    AND o.is_ms_shipped = 0

    AND o.object_id = OBJECT_ID(RTRIM('TableName'))

    ______________________________________________________________________________Never argue with an idiot; Theyll drag you down to their level and beat you with experience

  • Dave62 (1/31/2013)


    GilaMonster (1/31/2013)


    The row count in sysindexes is not related to statistics updates.

    This quote from the MSDN page I referenced seems to indicate some relation.

    "Counts the total number of inserted, deleted, or updated rows since the last time statistics were updated for the table."

    That's the rowmodctr column, not rows.

    Rowmodctr = row modification counter, number of rows changed since that statistic was last updated. Set to 0 when the index is rebuilt or stats updated. Replaced by the colmodctr in SQL 2005 and above.

    The column 'Rows' is the total number of rows in the index.

    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

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

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