【问题标题】:Get SELECT COUNT asynchronously continuously连续异步获取SELECT COUNT
【发布时间】:2026-01-28 00:40:02
【问题描述】:

我正在使用 jquery 数据表来显示一个网格,该网格使用 webapi 来检索它的数据。 webapi 使用 linq 来查询 mssql 数据库,它巧妙地使用过滤、排序和跳过/获取来在包含大约一百万条记录(并且还在增长)的索引良好的表上组装它的查询。一个常见的场景。

而且它的表现非常好。浏览器必须等待大约 50 毫秒才能返回响应(例如在分页时)。

但是,在我使用分析工具查看后,我注意到仅选择表的总行数大约需要 25 毫秒。我想知道,因为我希望数据表显示如下内容:“显示从 1.000.000 中过滤出来的 45.000 的第 1 到 10 行”需要总数。

我实际上不需要知道来自服务器的每次行程的精确总计数(它只是提供信息),所以我也许可以保留价值服务器端并在不同的任务中每秒刷新它,而不会干扰数据检索的数据表。我只会返回总行数的“足够接近”的值。

是否有可靠的机制?我尝试将总行数放在多个用户在多个回调期间使用的静态中,并且每次请求它时都会触发异步任务来刷新它。

这感觉很恶心,但是,共享静态内容并进行不同的线程更新对我来说并不是那么稳定。我查看了 SqlDependency 以在每次从我的数据更改到我的域模型时推送记录计数,但这似乎不支持 SELECT COUNT(Id) FROM TABLE 方案。

有什么想法吗?

【问题讨论】:

  • 使用绝对过期的MemoryCache 条目怎么样?
  • 当然,在 Web 场景中比静态更好。我同意,但是如何以稳定的方式更新它。
  • “稳定”是什么意思?更新的一种选择是使用 CacheItemPolicy 添加它,其中包括一个 RemovedCallback ,这将使调用再次获取计数。
  • 将绝对到期时间设置为约 1 秒是否有效?我需要最新的值始终可用,即使它正在刷新它。当我对 removecallback 采取行动时,我会说这个值已经消失了。对吗?
  • 是的,这只是我想到的第一件事,可能不适用于您的具体情况。

标签: c# asp.net-web-api datatables


【解决方案1】:

如果可能,您可以使用其中一个系统表。您可以每分钟 ping 一次并将其保存在缓存中。这个article 有两个它声称是足够的选项:

--The way the SQL management studio counts rows (look at table properties, storage
--, row count).  Very fast, but still an approximate number of rows.
SELECT CAST(p.rows AS float)
FROM sys.tables AS tbl
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int)
AND p.index_id=idx.index_id
WHERE ((tbl.name=N'Transactions'
AND SCHEMA_NAME(tbl.schema_id)='dbo'))

--Quick (although not as fast as method 2) operation and equally important, reliable.
SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('Transactions')   
AND (index_id=0 or index_id=1);    

【讨论】:

  • 那是一篇非常有趣的文章。我一定会试一试的。然而,不利的一面似乎是我需要与我相对干净和简单的代码优先模型有很大的不同,以将查询合并到系统表中。不过,我会考虑的。谢谢。
【解决方案2】:

您是否考虑过在执行查询时进行计数,然后通过 SignalR 将值回显给您的客户?

基本上,当 LINQ 调用返回时,获取一个 .Count() 并将值传递给后台线程,让 SignalR 通知客户端更新,同时将数据返回给请求客户端。

SignalR 将在所有客户端页面中激活一个 javascript 函数,然后您可以在其中获取传入的值并将其显示在页面的某个位置。

http://www.asp.net/signalr

【讨论】:

  • 其实我没有考虑过。这是一个有趣的方法,它可以工作,因为 Web 应用程序的所有用户都在查看具有相同总记录数的同一张表。我可以将它与页面加载的第一个值结合起来,只需将它放在我的剃须刀中即可。之后我使用信号器更新它。有趣的。谢谢。如果我尝试一下,我会告诉你的。
  • 我现在使用这种技术在某些场景中为我的用户实际填充表数据。当数据更新时,我对其进行一次查询,然后将整个结果发送给客户端。 1 次点击数据库,每个人都会收到更新。
  • 听起来不错,但我只能用它来计算总数。用户的浏览器中有复杂的客户端过滤器。当他们查看同一张表时,他们肯定不会查看相同的结果集。然而,我并没有真正用信号器做任何有用的事情,所以这可能是一件有趣的事情。我仍然需要某种服务器端计时器来获取最新的总数。而且在 MVC 中使用线程循环看起来很丑。