Adi*_*Adi 35 sql sql-server sql-server-2005 count sql-server-2008
计算具有大量数据的表可能非常慢,有时需要几分钟; 它还可能在繁忙的服务器上生成死锁.我想显示实际值,NOLOCK不是一个选项.
我使用的服务器是SQL Server 2005或2008 Standard或Enterprise - 如果重要的话.我可以想象SQL Server维护每个表的计数,如果没有WHERE子句,我可以很快得到这个数字,对吗?
例如:
SELECT COUNT(*) FROM myTable
Run Code Online (Sandbox Code Playgroud)
应立即返回正确的值.我是否需要依赖统计数据进行更新?
Aar*_*and 58
非常近似(忽略任何飞行中的交易)将是:
SELECT SUM(p.rows) FROM sys.partitions AS p
INNER JOIN sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas AS s
ON s.[schema_id] = t.[schema_id]
WHERE t.name = N'myTable'
AND s.name = N'dbo'
AND p.index_id IN (0,1);
Run Code Online (Sandbox Code Playgroud)
这将返回更快,更快COUNT(*),并且如果你的表变化足够快,它实际上并不那么准确 - 如果你的表在你开始你的COUNT(和锁被采取)和它被返回(当锁定时)之间发生了变化已经被释放,所有等待的写入事务现在都被允许写入表格,是否更有价值?我不这么认为.
如果你想要计算表的某个子集(比方说WHERE some_column IS NULL),你可以在该列上创建一个过滤索引,并根据它是异常还是规则来构造where子句,这取决于它是异常还是规则(所以在较小的集合上创建过滤的索引).所以这两个指标之一:
CREATE INDEX IAmTheException ON dbo.table(some_column)
WHERE some_column IS NULL;
CREATE INDEX IAmTheRule ON dbo.table(some_column)
WHERE some_column IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)
然后你可以用类似的方式得到计数:
SELECT SUM(p.rows) FROM sys.partitions AS p
INNER JOIN sys.tables AS t
ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas AS s
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.indexes AS i
ON p.index_id = i.index_id
WHERE t.name = N'myTable'
AND s.name = N'dbo'
AND i.name = N'IAmTheException' -- or N'IAmTheRule'
AND p.index_id IN (0,1);
Run Code Online (Sandbox Code Playgroud)
如果你想知道相反的情况,你只需从上面的第一个查询中减去.
Naj*_*ero 10
("大量数据"有多大? - 应该首先对此进行评论,但也许下面的执行官已经帮助你了解)
如果我在静态机器上运行查询(意味着没有其他人在很长一段时间内读取/写入/更新都很烦人,那么争用不是问题)表格在我的开发机器上在15秒内有2亿行和COUNT(*)甲骨文).考虑到纯数据量,这仍然很快(至少对我来说)
如你所说NOLOCK不是一个选项,你可以考虑
exec sp_spaceused 'myTable'
Run Code Online (Sandbox Code Playgroud)
同样.
但这与NOLOCK几乎相同(忽略争用+删除/更新afaik)