Quickest way to get the row count of a table

Note: This is not provide a transactionally consistent count

You often need to find out the number of rows in a table. However running a SELECT COUNT(*) FROM TABLE can be very slow.

From SQL 2005 onwards the system catalogues manitain the row count for a table, and unlike in previous versions it is maintain in real time and I have heard should always be correct, if you find it isn't then please provide me a repro. 

So the quickest way to get the row count is to run a query like

select top 1 rows

from sys.partitions

where object_id = object_id(@tablename)

This returns the rows figure from the catalogue view sys.partitions

[SS 14/1/2010 18:45 Guaranteed is probably not the correct word, especially as BOL states it is approximate. I am awaiting confirmation under what circumstances the number will be approximate]

For partitioned tables you have to go a bit further

select sum(rows) as row_count

 from sys.partitions

where index_id in (0,1)

  and object_id = object_id(@table) 

Thanks the comments and emails highlighting my faux pas

[SS 14/1/2010 18:45 Update following email exchange with Rubén Garrigós]

He also pointed out that the count isn't transactional.This is very true as it would cause a large amount of blocking. You can see this by running the following

create table fred (col1 int)

go

begin transaction

set nocount on

declare @i int = 0

while @i < 100000

begin

insert into fred values (@i)

set @i = @i + 1

end

And then running this in a different connection

select * from sys.partitions

where object_id = object_id ('fred')

You will see 100000 as the rows number.

So in summary the number you get is up to date but not transactionally conistent, it doesn't adhere to any of the isolation levels. However if you have a very large table that might not make a difference, the difference between 1000000  and 1000203 may not count, so only use this as a guide. Don't use this in any calculations that your finance Director will be basing decisions on.

The key point is that this number is maintained in realtime, it doesn't require some back ground process to go through and update it as it did in previous versions.

 


Published 14 January 2010 16:17 by simonsabin

Comments

14 January 2010 17:32 by DonRWatters

# re: Quickest way to get the row count of a table

Assuming your table isn't partitioned.

14 January 2010 18:46 by simonsabin

# re: Quickest way to get the row count of a table

Yeh fair point. If you are using partitioning you need to sum the rows for a particular index id 0 or 1 if heap or clustered table. The top 1 is the simplest if you don't have partitioning. Thanks to Bob Stefkovich for also emailing me about this.

14 January 2010 18:48 by BobS

# re: Quickest way to get the row count of a table

Here's a variation that can handle partioned and non-partitioned tables.

select sum(rows) as row_count

from sys.partitions

where index_id in (0,1) -- heap or clustered index

and object_id = object_id(@tablename)

14 January 2010 20:37 by crandall

# re: Quickest way to get the row count of a table

Assuming you have at least one non-filtered index on the table, you can still use SELECT COUNT(*) without the scan penalty. See Paul Randal's blog for more:

www.sqlskills.com/.../Which-index-will-SQL-Server-use-to-count-all-rows.aspx

14 January 2010 20:50 by simonsabin

# re: Quickest way to get the row count of a table

You are still having to scan an index. Rather than just query a single value.

15 January 2010 01:25 by simonsabin

# re: Quickest way to get the row count of a table

I got this from Marcel van der Holst who is part of the Microsoft SQL Server Storage Engine

"The row count number in sys.partitions is not necessarily transaction consistent. If you stop all queries in the server, and compare the rowcount in sys.partitions and count(*) you will get the same value. (If not, it's a bug in the engine, assuming you have updated the rowcounts in sys.partitions after you upgraded to SQL2005).

However, when inserts/deletes are done against the table and the transactions have not committed yet, the value of count(*) and rowcount in sys.partitions don't necessarily match. The reason is that the rowcount in sys.partitions is updated non-transactionally. During normal operation, when an insert is done, we increment the rowcount, and when a rollback happens the rowcount is decremented. However, a count(*) would block in this case, as there is a new row that is not visible. So count(*) will give you the old row count before the insert, while sys.partitions might give you the before rowcount, rowcount when the row was inserted, or the rowcount when the insert was rolled back.

If you need a transactionally consistent rowcount, you need to use count(*) from the table. If you want to have some idea of how many rows there are in the table, but you don't care about the exact number, you could use the sys.partitions column. However, there are some cases where the number could be way off. For instance, bulk insert batches the count of rows that are inserted, and only updates sys.partitions at the end of each internal batch (every 8 extents or so)."

Thanks,

Marcel.

# Twitter Trackbacks for Quickest way to get the row count of a table - Simon Sabin UK SQL Consultant's Blog [sqlblogcasts.com] on Topsy.com

Pingback from  Twitter Trackbacks for                 Quickest way to get the row count of a table - Simon Sabin UK SQL Consultant's Blog         [sqlblogcasts.com]        on Topsy.com

15 January 2010 13:19 by steveh99999

# re: Quickest way to get the row count of a table

Simon, how does this compare to using the rowcnt column from sysindexes ?

15 January 2010 20:31 by simonsabin

# re: Quickest way to get the row count of a table

sysindexes is a compatibility view which uses this data. So its the same

15 January 2010 23:41 by SqlServerKudos

# Quickest way to get the row count of a table

Kudos for a great Sql Server article - Trackback from SqlServerKudos