是什么让count(*)查询运行30秒?

时间:2014-01-21 13:44:39

标签: sql sql-server

我有一个MS SQL表,行数超过2.5亿。每当我执行以下查询

SELECT COUNT(*) FROM table_name

我需要30秒才能获得输出。为什么要花这么多时间?当我查询时这会计数吗?我假设它在某个地方存储了这个信息(可能在表元数据中。我不确定表元是否存在)。

另外,我想知道这个查询是否是IO /处理器/内存密集型?

由于

4 个答案:

答案 0 :(得分:4)

每次执行SELECT COUNT(*) from TABLE SQL服务器实际上都会遍历表并计算所有行。要在一个或多个表上获得estemated行计数,您可以运行以下查询,该查询获取存储的信息并在1秒内返回。

SELECT OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

在此处详细了解http://technet.microsoft.com/en-us/library/ms187737.aspx

答案 1 :(得分:0)

不,sql server不存储此信息。它计算每个查询。但它可以缓存执行计划以强化性能。因此,如果您想快速获得结果,至少需要一个主键。

答案 2 :(得分:0)

如果您正在寻找表的近似计数,并且您的版本大于或等于SQL Server 2005,则可以使用:

SELECT t.NAME AS 'TableName'
,s.Name AS 'TableSchema'
,p.rows AS 'RowCounts'
FROM sys.tables t
INNER JOIN sys.schemas s 
  ON t.schema_id = s.schema_id
INNER JOIN sys.indexes i 
  ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p 
  ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE 
t.is_ms_shipped = 0
GROUP BY
t.NAME, s.Name, p.Rows
ORDER BY 
s.Name, t.Name

执行计数(*)只会占用少量内存/处理器。就数据库功能而言,它并不是那么大的操作。

答案 3 :(得分:0)

至于SQL服务器正在做什么以及它有多贵,你可以自己查看一下。在SSMS中启用查询的执行计划按钮并运行select count(*)。您将看到服务器实际执行索引扫描(全表扫描)。 (我本来期望将PK用于此,但在我的测试用例中,它使用了其他一些非聚集索引。)。

要了解费用,请右键单击查询编辑器窗口,选择Query Options... -> Execution -> Advanced并激活SET STATISTICS TIMESET STATISTICS IO的复选框。在重新执行select语句后,“消息”选项卡将包含有关IO和计时的信息。

另请注意,就其使用的共享锁而言,选择计数(*)非常激进。为了保证结果,整个表格将被shared lock锁定。

非常快速,无锁的替代方法是使用表的元数据。从元数据中获得的计数几乎总是准确的,但不能保证。

USE <database_name,,>
GO

SELECT ddps.row_count
FROM   sys.indexes AS i
       INNER JOIN sys.objects AS o
         ON i.object_id = o.object_id
            AND o.name = '<your_table,,>'
       INNER JOIN sys.dm_db_partition_stats AS ddps
         ON i.object_id = ddps.object_id
            AND i.index_id = ddps.index_id
WHERE  i.index_id = 1

这是SSMS模板。将其复制到查询窗口并按CTRL + SHIFT + M以获取一个对话框,询问您是否为database_name和table_name的值。