SELECT COUNT(*) FROM tableA 在千萬行大表上極慢(DELL 4400 測試:100萬行耗時 1 分鐘+)。聚簇索引首次執行同樣慢,後續雖快但大量增刪後又退化,且大表不適合建聚簇索引(嚴重拖慢增刪)。
每個表在 sysindexes 系統表至少有一行記錄,rows 列**定時記錄表行數**:
| 列 | 類型 | 含義 |
|---|---|---|
id | int | 表 ID(indid=0 或 255 時),否則為索引所屬表 ID |
indid | smallint | 0=堆表,1=聚簇索引,>1=非聚簇索引,255=含 text/image 的表條目 |
rows | int | 基於 indid=0 和 1 的數據行數,indid>1 重復此值,indid=255 時為 0 |
無聚簇索引時 indid=0,有聚簇索引時 indid=1。
SELECT rows
FROM sysindexes
WHERE id = OBJECT_ID('tablename')
AND indid IN (0, 1)
速度比 COUNT(*) **快數萬倍**,毫秒級完成。
rows,而是定時更新(Checkpoint/統計更新時)
DBCC UPDATEUSAGE('DatabaseName', 'TableName') WITH ROW_COUNTS
-- 然後再查 sysindexes.rows
首次執行耗時大,效果等同聚簇索引表的 COUNT(*)。
聚簇索引表 COUNT(*) 走葉級掃描,極快。但**大表頻繁增刪不宜建聚簇索引**(頁分裂嚴重)。
| 需求 | 推薦方案 | 代價 |
|---|---|---|
| 粗略估算、極速 | sysindexes.rows | 毫秒,非精確 |
| 精確、可接受秒級 | DBCC UPDATEUSAGE + sysindexes.rows | 首次同步慢,後續快 |
| 精確、高頻查詢、寫入少 | 建聚簇索引 + COUNT(*) | 寫入性能犧牲 |
| 精確、高頻寫入 | 應用層維護計數表 / 觸發器同步 | 開發成本,寫入微增 |
-- DMV 方式,準確且快
SELECT SUM(p.rows)
FROM sys.partitions p
WHERE p.object_id = OBJECT_ID('tablename')
AND p.index_id IN (0, 1)
sysindexes.rows 是「快速估算」神器;精確計數視業務權衡選擇 DBCC UPDATEUSAGE、聚簇索引或應用層計數表。**不要在大表高頻執行 COUNT(*) 無索引掃描**。