Sql 计数(*)与sys.partitions中的行不同
我使用以下查询获取数据库中所有表的信息:Sql 计数(*)与sys.partitions中的行不同,sql,sql-server,database-schema,Sql,Sql Server,Database Schema,我使用以下查询获取数据库中所有表的信息: SELECT t.NAME AS TableName, i.name as indexName, sum(p.rows) as RowCounts, sum(a.total_pages) as TotalPages, sum(a.used_pages) as UsedPages, sum(a.data_pages) as DataPages, (sum(a.total_pages) * 8)
SELECT
t.NAME AS TableName,
i.name as indexName,
sum(p.rows) as RowCounts,
sum(a.total_pages) as TotalPages,
sum(a.used_pages) as UsedPages,
sum(a.data_pages) as DataPages,
(sum(a.total_pages) * 8) / 1024 as TotalSpaceMB,
(sum(a.used_pages) * 8) / 1024 as UsedSpaceMB,
(sum(a.data_pages) * 8) / 1024 as DataSpaceMB
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
WHERE
t.NAME NOT LIKE 'dt%' AND
i.OBJECT_ID > 255 AND
i.index_id <= 1
GROUP BY
t.NAME, i.object_id, i.index_id, i.name
ORDER BY
object_name(i.object_id)
为什么呢
编辑:
第一个查询返回更高的计数:
First: 1 240 464
Second: 413 496
内部联接将导致筛选出不匹配的行。组还将影响行数,因为它们可以合并行。这两个条件导致聚合查询的行计数低于简单计数(*) 我明白了,您具体询问的是sys.partitions表。可能的解释是,给定i.object\u id=p.object\u id和i.index\u id=p.index\u id的匹配条件,sys.indexes表中的每一行都不匹配。请尝试运行以下操作:
Select
count(*)
from
sys.partitions p
LEFT JOIN
sys.indexes i ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
然后您可能会看到您期望的计数。删除count函数,只需选择*..即可找到不匹配的行。内部联接将导致筛选出不匹配的行。组还将影响行数,因为它们可以合并行。这两个条件导致聚合查询的行计数低于简单计数(*) 我明白了,您具体询问的是sys.partitions表。可能的解释是,给定i.object\u id=p.object\u id和i.index\u id=p.index\u id的匹配条件,sys.indexes表中的每一行都不匹配。请尝试运行以下操作:
Select
count(*)
from
sys.partitions p
LEFT JOIN
sys.indexes i ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
然后您可能会看到您期望的计数。删除计数功能,只需选择*..即可找到不匹配的行。您是否查阅了有关
sys.allocation\u units
视图的帮助文章?显然,container\u id
字段比看起来稍微多了一点。尝试将其添加到的where
部分:
and a.type = 2
您是否查阅了有关
sys.allocation\u units
视图的帮助文章?显然,container\u id
字段比看起来稍微多了一点。尝试将其添加到的where
部分:
and a.type = 2
从
rows bigint此分区中的大致行数。
(我的重点)。系统视图不会在表中保留行数。想想这会带来什么,以及它会给所有insert/delete语句增加多少开销。如果我是一个赌徒,我会说它是在计算聚集索引或堆中的页数,这是一个更便宜的操作。不过,这纯粹是推测。来自
rows bigint此分区中的大致行数。
(我的重点)。系统视图不会在表中保留行数。想想这会带来什么,以及它会给所有insert/delete语句增加多少开销。如果我是一个赌徒,我会说它是在计算聚集索引或堆中的页数,这是一个更便宜的操作。不过,这纯粹是推测。问题在于每个分区有多个分配单元,因此同一个分区可能会出现多次,因此总和(p.rows)最终会对同一分区进行多次计数,因此得到正确行数的倍数 下面是我如何解决这个问题的: (请注意,我的查询与您的查询不同,我的列略有不同,使用的是Kb而不是Mb,但想法是一样的)
问题是每个分区有多个分配单元,因此同一个分区可能会出现多次,因此总和(p.rows)最终会对同一个分区进行多次计数,从而得到正确行数的倍数 下面是我如何解决这个问题的: (请注意,我的查询与您的查询不同,我的列略有不同,使用的是Kb而不是Mb,但想法是一样的)
在SQL Server 2016中,为了修复
计数(*)
和sys.partitions
不匹配,我对主键执行了索引重建。幸运的是,该表只有240万行,所以只要我有standard edition,就不用花那么长时间,所以无法在线重建。在SQL Server 2016中,为了修复计数(*)
和sys.partitions
不匹配,我对主键执行了索引重建。幸运的是,该表只有240万行,所以我没有花那么长时间使用standard edition,因此无法在线进行重建。问题在于它是另一种方式。您看到行数更高了吗?在这种情况下,sys.indexes表中必须有重复项。将我发布的查询更改为右连接,您应该会看到它们。问题是,情况正好相反。您看到的行数更高?在这种情况下,sys.indexes表中必须有重复项。将我发布的查询更改为正确的联接,您应该会看到它们。这是正确的见解,但不是正确的解决方案。因为每个分区可以有多个分配单元,所以同一分区可能会出现多次,因此总和(p.rows)最终会对同一分区进行多次计数。这是正确的见解,但不是正确的解决方案。因为每个分区可以有多个分配单元,同一个分区可以出现多次,因此总和(p.rows)最终会对同一分区进行多次计数。这个答案是不正确的:确实,计数是近似的,但真正的问题是,查询是错误的,因为它会导致同一分区的行被多次求和,因此您将得到正确的(如果是近似的)答案乘以存在的分配单元数。如果给定分区有多个AU(即IN_ROW_数据和LOB_数据),则可能会重复计算。一个简单的修复方法是在原始查询中添加一个谓词,以获取行内数据,或者对找到的所有AU进行平均。但是说它不正确有点强烈;关于sys.bein中的行数,我的原始答案中的所有内容都是正确的