使用dm_db_partition_stats

时间:2018-04-06 15:22:34

标签: sql sql-server

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

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的行数是多少?

感谢。

UPDATE-1

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

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

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

使用“从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,但我想知道我是否可以某种方式执行连接或类似的东西,以便立即为我提供总行数但需要过滤而不是而不是适用于整个表。

感谢。

1 个答案:

答案 0 :(得分:0)

你有没有问过阿尔法半人马的指示?没有?那么答案是,你无法从这里到达那里。

添加索引,重新组织/重新构建,更新统计数据只会让你到目前为止。你应该考虑改变你的方法。

sp_spaceused通常会立即返回记录计数;您可能可以使用此功能,但是依赖于(您还没有给我们足够的信息)您使用计数的内容可能不够。

我不确定您是否尝试将此计数用作短路更大操作的方法或您在应用程序中使用计数的方法。当您开始突出显示14亿条记录并且您正在寻找所述集合中的窗口时,听起来您可能是分区表的候选者。

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

Kimberly Tripp有一个博客和一些视频,Kendra Little也有一些很好的内容,如何使用它们以及如何设置它们。这将是一次设计变更。它有点复杂,而不是你想要实现的东西。

以下是金佰利博客的链接:https://www.sqlskills.com/blogs/kimberly/sqlskills-sql101-partitioning/

  开玩笑:

另外,我听说你指责SQL,你是不是偶然使用了实体框架?