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中的行数,我的原始答案中的所有内容都是正确的