Sql 使用dm_db_partition_stats获取筛选的行计数

Sql 使用dm_db_partition_stats获取筛选的行计数,sql,sql-server,Sql,Sql Server,我在我的应用程序中使用了分页,但我注意到分页速度非常慢,下面的一行是罪魁祸首: SELECT COUNT (*) FROM MyTable 在我仅有900万行的表中,返回行数需要43秒。我在另一篇文章中读到,返回14亿行的行数需要5分钟以上。这显然不能用于分页,因为它太慢了,我需要行计数的唯一原因是计算可用页面的数量 经过一段时间的研究,我发现我可以通过以下方法立即(准确)获得行数: SELECT SUM (row_count) FROM sys.dm_db_partition_stats W

我在我的应用程序中使用了分页,但我注意到分页速度非常慢,下面的一行是罪魁祸首:

SELECT COUNT (*) FROM MyTable
在我仅有900万行的表中,返回行数需要43秒。我在另一篇文章中读到,返回14亿行的行数需要5分钟以上。这显然不能用于分页,因为它太慢了,我需要行计数的唯一原因是计算可用页面的数量

经过一段时间的研究,我发现我可以通过以下方法立即(准确)获得行数:

SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('MyTable')
AND (index_id=0 or index_id=1)
但是上面返回的是整个表的计数,如果没有应用筛选器,这是可以的,但是如果需要应用筛选器(如日期范围和/或状态),我该如何处理

例如,当DateTime字段介于2013-04-05和2013-04-06之间且状态为“警告”时,MyTable的行数是多少

谢谢

更新-1

如果我不清楚,我需要可用行的总数,以便在使用“分页”功能时确定与查询匹配的所需页数。例如,如果一个页面返回20条记录,而与我的查询匹配的记录总数为235条,我知道我需要在网格下方显示12个按钮

01-(第1行到第20行)-网格中显示20行。 02-(第21至40行)-网格中显示20行。 ... 11-(第200至220行)-网格中显示20行。 12-(第221行至第235行)-网格中显示15行

将添加额外的逻辑来处理大量页面,但这是一个UI问题,因此这超出了本主题的范围

我使用“Select count(*)from MyTable”的问题是,在900万条记录上花费了40秒以上的时间(虽然不再是了,但我需要找出原因!),但使用这种方法,我能够添加与查询相同的过滤器来确定查询。比如说,

SELECT COUNT(*) FROM [MyTable]
WHERE [DateTime] BETWEEN '2018-04-05' AND '2018-04-06' AND
      [Status] = 'Warning'
一旦确定了页面数,我将运行相同的查询,但包括字段而不是count(*)、CurrentPageNo和PageSize,以便使用行ID按页码筛选结果,并在需要时导航到特定页面

SELECT RowId, DateTime, Status, Message FROM [MyTable]
WHERE [DateTime] BETWEEN '2018-04-05' AND '2018-04-06' AND
      [Status] = 'Warning' AND
      RowId BETWEEN (CurrentPageNo * PageSize) AND ((CurrentPageNo + 1) * PageSize)
现在,如果我使用前面提到的另一种方法来获取行数,即

SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('MyTable')
AND (index_id=0 or index_id=1)
它会立即返回计数,但我如何过滤它,以便可以像使用
SELECT count(*)
方法一样包含相同的过滤器,这样我就可以得到如下结果:

SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('MyTable') AND 
(index_id=0 or index_id=1) AND
([DateTime] BETWEEN '2018-04-05' AND '2018-04-06') AND
([Status] = 'Warning')
当我查询dm_db_partition_stats时,上面的清除将不起作用,但是我想知道我是否可以以某种方式执行连接或类似的操作,以立即向我提供总行数,但是需要对其进行过滤,而不是应用于整个表


谢谢。

你问过半人马座阿尔法星的方向吗?不答案是,你不能从这里到达那里

添加索引、重新组织/重新构建、更新统计数据只会让你走到这一步。你应该考虑改变你的方法。

sp_spaceused通常会立即返回记录计数;您可能能够使用此功能,但是,根据您使用计数的目的(您没有向我们提供足够的信息),这可能是不够的

我不确定您是否试图使用此计数作为短路更大操作的手段,或者在应用程序中如何使用计数。当您开始突出显示14亿条记录,并在所述集合中寻找一个窗口时,听起来您可能是分区表的候选对象

这允许您分配几个较小的表,通常以日期、年/月分隔,作为单个表。当您给出14亿多条记录的日期范围时,SQL可以满足性能预期。这确实取决于SQL版本,但也有视图分区

Kimberly Tripp有一个博客和一些视频,Kendra Little也有一些关于如何使用和设置它们的好内容。这将是一个设计上的改变。这有点复杂,不是你一时兴起想要实现的东西

以下是金伯利博客的链接:

开发人员玩笑:


另外,我听到你在责怪SQL,你是不是碰巧使用了entity framework?

你最快的结果可能是进行计数(*)查询并为过滤器中的列编制索引。要么这样做,要么构建(并维护)一个预聚合的表。@TabAlleman奇怪,在阅读了您的回复后,我正要回复说我的表已经有了一个主键,我认为它已经足够了,但当我运行一个基本的select计数(*)时,我注意到它没有花43秒,而是花了1秒,然后我去了hmmm???我所做的唯一一件事就是在我的DateTime字段上添加了一个索引,但这个索引没有被使用,因为我还没有按DateTime进行筛选,所以我很困惑,为什么现在执行得这么快。仍然比我希望的要慢,更希望是一个即时的结果,但这已经好得多了。我将对此进行进一步研究并发布更新。我已经用其他信息更新了我的问题。希望这能澄清你的一些疑问。此外,我正在使用实体框架,但从外观上看,我将不再使用它。不责怪SQL:)。我只是想弄清楚如何立即获得“过滤行数”。关于14亿美元,谢谢你,但不会很快出现,所以现在我们暂且不谈这个。我刚才提到它是为了将时间作为一个示例来强调执行“选择计数(*)所需的时间。