我同意杰克的观点。 I count(*) 是一种快速获取行数的方法,但是,您可能需要进行聚集索引扫描。对于小型数据集,这不是问题。
另一方面,您可以使用系统目录视图。但是,这些会根据某个后台线程进行更新。对于多 TB 数据集,目录查找可能会更快。
根据系统事件,计数可能准确也可能不准确。
http://sqlblog.com/blogs/kalen_delaney/archive/2009/12/07/how-many-rows.aspx
这完全取决于您需要的准确度。如果是账本数据,那么非常准确。如果是预测数据,可能不太准确。
我建议使用 RCSI 而不是默认的 READ COMMITTED 以获得更好的时间点计数。这是使用 SELECT COUNT(*) FROM [TABLE] 语法。
http://www.sqlpass.org/summit/2013/Sessions/SessionDetails.aspx?sid=4730
Randy Knight 去年对此进行了精彩的介绍。
您还可以查看我的隔离演示文稿,其中的代码表明 READ COMMITTED 可能不准确。
http://craftydba.com/?page_id=880
下面列出了三种解决方案。
祝你好运
J
-- Show time & i/o
SET STATISTICS TIME ON
SET STATISTICS IO ON
GO
-- Remove clean buffers & clear plan cache
CHECKPOINT
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
-- test database
use adventureworks2012
go
-- traverse the table
select count(*) as 'rows' from person.address
go
/*
SQL Server 解析和编译时间:
CPU 时间 = 0 毫秒,经过的时间 = 0 毫秒。
(1 行受影响)
表“地址”。扫描计数 1,逻辑读取 36,物理读取 1,预读读取 34,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
SQL Server 执行时间:
CPU 时间 = 15 毫秒,运行时间 = 26 毫秒。
*/
-- Look at sysindexes
select o.name as 'Table', max(i.rows) 'Rows'
from sysobjects o join sysindexes i
on o.id = i.id
where
(i.indid = 1 or i.indid = 0) and
o.type = 'U' and
o.name = 'Address'
group by o.name
go
/*
SQL Server 解析和编译时间:
CPU 时间 = 15 毫秒,运行时间 = 132 毫秒。
(1 行受影响)
表 'sysidxstats'。扫描计数 1,逻辑读取 2,物理读取 2,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表'sysschobjs'。扫描计数 1,逻辑读取 6,物理读取 3,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,运行时间 = 36 毫秒。
*/
-- Look at sys.partitions
SELECT max(rows) as 'Rows' FROM sys.partitions
WHERE object_id = object_id('Person.Address');
/*
SQL Server 解析和编译时间:
CPU 时间 = 16 毫秒,运行时间 = 104 毫秒。
(1 行受影响)
表“工作台”。扫描计数 0,逻辑读取 0,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表 'sysidxstats'。扫描计数 1,逻辑读取 10,物理读取 2,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表'sysschobjs'。扫描计数 0,逻辑读取 4,物理读取 2,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表 'sysrowsets'。扫描计数 1,逻辑读取 6,物理读取 1,预读读取 24,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,经过的时间 = 34 毫秒。
*/