September 8, 2011 at 9:08 am
I've found a lot of conflicting information about the accuracy of different methods for obtaining a table's row count, specifically sys.dm_db_partition_stats. I need to get a count for the size of all tables within a database that contains MANY tables, and I'd like to make that process as quick as possible. I'm on SQL 2008. We did upgrade from SQL 2000, but I ran a DBCC UPDATEUSAGE during the upgrade process.
My understanding is that a SELECT COUNT(*) FROM MyTable will perform a table scan to obtain the current count of committed rows in the table, but that method is very slow when I have to iterate over all the tables in the DB. A set-based approach makes way more sense here.
For instance:
SELECT object_id,
SUM(ps.row_count)
FROM sys.dm_db_partition_stats
WHERE index_id = 0
OR index_id = 1
GROUP BY object_id
How does sys.dm_db_partition_stats compare? Are there any instances where the DMV would not be accurate for all committed transactions?
September 9, 2011 at 9:17 am
I believe it's accurate, but not transactionally consistent, so you could potentially see counts that were later rolled back.
In reality, I don't see many cases where that would present a problem. What are you using the counts for that requires them to be so accurate to a point in time?
September 9, 2011 at 9:32 am
HowardW (9/9/2011)
What are you using the counts for that requires them to be so accurate to a point in time?
It's record counts for customer data imports. Truthfully it's probably OK if they aren't accurate, but it's the type of thing that inevitably leads to support requests when the record count doesn't match the customer's expectation.
If the DMV is correct other than current transactions, that's probably "good enough", and any errors would likely be corrected on the next run of the query.
September 9, 2011 at 11:00 am
USE Database_name
GO
SP_SPACEUSED 'yourschema.yourtablename'
GO
The above gives the number of rows and other information regarding the table. This is the faster way to see the number of commited rows in a table.
September 9, 2011 at 11:15 am
mysearchresult (9/9/2011)
USE Database_nameGO
SP_SPACEUSED 'yourschema.yourtablename'
GO
The above gives the number of rows and other information regarding the table. This is the faster way to see the number of commited rows in a table.
Did you check what SP_SPACEUSED is using to calculate the number of rows? (sys.dm_db_partition_stats, as above)
September 9, 2011 at 11:43 am
mysearchresult (9/9/2011)
USE Database_nameGO
SP_SPACEUSED 'yourschema.yourtablename'
GO
The above gives the number of rows and other information regarding the table. This is the faster way to see the number of commited rows in a table.
In my case I'm looking to get the rowcount for many tables at once, so the DMV is actually more efficient since I don't have to call the stored proc over and over again.
September 9, 2011 at 11:44 am
md23 (9/9/2011)
mysearchresult (9/9/2011)
USE Database_nameGO
SP_SPACEUSED 'yourschema.yourtablename'
GO
The above gives the number of rows and other information regarding the table. This is the faster way to see the number of commited rows in a table.
In my case I'm looking to get the rowcount for many tables at once, so the DMV is actually more efficient since I don't have to call the stored proc over and over again.
Ok, Only 1 call to a sp (not the best way to go about it, but still fun to know) =>
SET STATISTICS IO, TIME OFF
SET NOCOUNT ON
SET IMPLICIT_TRANSACTIONS ON
GO
USE [master]
GO
IF OBJECT_ID('dbo.spaceused', 'U') IS NULL
BEGIN
CREATE TABLE dbo.spaceused (
DbName sysname DEFAULT(''),
tblName sysname,
Row_count INT ,
Reserved VARCHAR(50),
data VARCHAR(50) ,
index_size VARCHAR(50),
unused VARCHAR(50),
PRIMARY KEY CLUSTERED (DbName, tblName)
);
END
ELSE
BEGIN
--DROP TABLE dbo.spaceused
TRUNCATE TABLE dbo.spaceused
END
COMMIT
GO
DECLARE @Cmd VARCHAR(8000)
SET @Cmd = 'USE [?];
IF ''?'' NOT IN (''tempdb''
--, ''master'', ''model'', ''msdb''
)
BEGIN
--PRINT ''?''
DECLARE @InnerCmd VARCHAR(8000)
SET @InnerCmd = ''
EXEC sp_spaceused '''''' + CHAR(63) + ''''''''
INSERT INTO master.dbo.spaceused(tblName, Row_count,Reserved,data,index_size,unused)
EXEC sp_MSforeachtable @InnerCmd
UPDATE master.dbo.spaceused SET DbName = ''?'' WHERE DbName = ''''
END
'
--PRINT @Cmd
EXEC sp_MSforeachdb @Cmd
DELETE FROM dbo.spaceused WHERE Row_count = 0
SELECT
DbName
, tblName
, Row_count
, CONVERT(BIGINT, REPLACE(Reserved, ' KB', '')) / 1024 AS MB_Reserved
, CONVERT(BIGINT, REPLACE(data, ' KB', '')) / 1024 AS MB_data
, CONVERT(BIGINT, REPLACE(index_size, ' KB', '')) / 1024 AS MB_index_size
, CONVERT(BIGINT, REPLACE(unused, ' KB', '')) / 1024 AS MB_unused
FROM
dbo.spaceused
ORDER BY
DbName
, MB_Reserved DESC
, Row_count DESC
COMMIT
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply