我在另一篇文章中读了这个讨论,其他人提出了这个问题。在阅读讨论之前,我一直认为SQL Server(和其他DBMS)会在元数据中的某个位置保留每个表的全局行计数,但是讨论似乎并不是这样。为什么?Count(*)(不进行任何过滤),如果它是O(1),那么这样的常见操作将获得巨大的提升。即使不考虑COUNT(*),表中的总行数也是这样的基本信息。他们为什么不记下来?
Count(*)
COUNT(*)
另外,为什么我们需要“装载”整行(如我链接的文章中所述)只是为了对它们进行计数?索引或PK等不应该足以计算它们吗?
不,COUNT(*)不是恒定时间操作。一个COUNT(*)必须返回符合当前扫描谓语(即行数WHERE条),让独自会使元数据属性无效的回报。但是,即使您没有谓词,COUNT仍必须满足当前的事务隔离语义,即。返回 可见 (例如已提交)的行数。因此COUNT,在SQL Server中必须而且将实际扫描并计算行数。一些系统允许返回更快的“估计”计数。
WHERE
COUNT
另外,作为附带说明,依靠rowsinsys.partitions是不可靠的。毕竟,如果可以保证此计数是准确的,那么我们将不需要DBCC UPDATEUSAGE(...) WITH COUNT_ROWS。从历史上看,有几种情况会导致此计数器偏离实际情况(大多数情况下日志记录的插入回滚最少),我所知道的都是固定的,但仍然存在以下问题:1)包含错误的早期版本的升级表和2 )其他尚未发现的错误。
rows
sys.partitions
DBCC UPDATEUSAGE(...) WITH COUNT_ROWS
这不是100%正确。至少有两种情况不“加载整行”:
而且我上面所说的大多数内容都不适用于Hekaton表格。