Does a SELECT COUNT(*) query have to do a full table scan?

我的梦境 提交于 2021-01-05 06:27:04

问题


Does a query that gets the count of all rows in a table have to do a full table scan or does SQL Server maintain a count of rows somewhere?

SELECT COUNT(*) FROM TABLE_NAME;

The table TABLE_NAME has a primary key, and therefore a clustered index, and looks like so:

CREATE TABLE TABLE_NAME
(
  Id int PRIMARY KEY IDENTITY(1, 1),
  Name nvarchar(50) NOT NULL
);

I am using Microsoft SQL Server 2014.


回答1:


The server will always read all records (if there's an index then it will scan the entire index) to count the rows. You can't escape this as long as you are doing SELECT COUNT(*) FROM Table.

If your table has a clustered index, you can change your query to an "under the hood" query to retrieve the count without actually fetching the records with:

SELECT OBJECT_NAME(i.id) [Table_Name], i.rowcnt [Row_Count]
FROM sys.sysindexes i WITH (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rowcnt desc

if you are looking for an approximate count of the records, you can also use the following query:

SELECT 
    TableName = t.NAME,
    SchemaName = s.Name,
    [RowCount] = p.rows,
    TotalSpaceMB = CONVERT(DECIMAL(18,2), SUM(a.total_pages) * 8 / 1024.0), 
    UsedSpaceMB = CONVERT(DECIMAL(18,2), SUM(a.used_pages) * 8 / 1024.0),
    UnusedSpaceMB = CONVERT(DECIMAL(18,2), (SUM(a.total_pages) - SUM(a.used_pages)) * 8 / 1024.0)
FROM 
    sys.tables t
    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
    INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
    LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, 
    s.Name, 
    p.Rows
ORDER BY 
    TotalSpaceMB DESC

This will show non-system tables with their calculated (not exact) row count and the sum of the sizes of their data (with any index they might have), relatively fast without retrieving the records.




回答2:


When SQL Server performs a query like SELECT COUNT(*), SQL Server will use the narrowest non-clustered index to count the rows. If the table does not have any non-clustered index, it will have to scan the table.

If your table has a clustered index you can get your count even faster.




回答3:


SELECT COUNT(*) FROM TABLE_NAME;

Does a full table scan.

For optimizations you can refer to this.




回答4:


you can following way. it is better in performance I guess.

SELECT COUNT(1) FROM TABLE_NAME 


来源:https://stackoverflow.com/questions/54921610/does-a-select-count-query-have-to-do-a-full-table-scan

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!