在数据库上创建变量以保存全局统计信息

时间:2011-06-03 11:45:14

标签: sql sql-server sql-server-2005 variables

让我假装我有一个社交网络。 我总是向用户显示已注册的用户数量并激活了他们的个人资料。 因此,每次单个用户登录时,都会转到DB并生成:

select count(*) from users where status = 'activated'

因此,如果5.000个用户登录,或者只是刷新页面,它将向上面的SQL发出5.000个请求。 我想知道是否有更好的变量某些地方(我仍然不知道放在哪里)每次用户激活他的个人资料时将添加1然后,当我想显示有多少用户注册到该社交网络时,我只会得到这个变量的值。

我该怎么做?它真的是一个更好的解决方案吗?

5 个答案:

答案 0 :(得分:2)

您可以使用SQL Server将自动维护的索引视图:

create table dbo.users (
    ID int not null,
    Activated bit not null
)
go
create view dbo.user_status_stats (Activated,user_count)
with schemabinding
as
    select Activated,COUNT_BIG(*) from dbo.users group by Activated
go
create unique clustered index IX_user_status_stats on dbo.user_status_stats (Activated)
go

这只有两种可能的状态,但可以使用不同的数据类型扩展到更多。正如我所说,在这种情况下,SQL Server将维护幕后的计数,因此您只需查询视图:

SELECT user_count from user_status_stats with (NOEXPAND) where Activated = 1

,它不必查询基础表。您需要在下面的版本(Enterprise / Developer)上使用WITH (NOEXPAND)提示。


虽然正如@Jim建议的那样,当索引列使用相等比较满足查询条件时,对索引执行COUNT(*)也应该很快。

答案 1 :(得分:1)

正如您已经猜到的那样 - 每次有人点击网站时计算这个值都不是一个好主意。

您可以按照建议进行操作,并在添加用户时更新中心值,但您必须确保最终不会同时更新数字的两个进程。

或者,您可以拥有一个定期运行SQL并更新中央“用户计数”值的作业。

或者#2,您可以使用MemCache之类的东西来保存一段时间的计算值,然后当缓存过期时,再次重新计算它。

答案 2 :(得分:0)

您可以考虑几个选项:

1)就像你说的那样,每次激活配置文件时都要保持全局计数,以便每次都保存用户表上的命中。您可以将该计数存储在“统计信息”表中,然后从那里查询该值。

2)不显示实际的“实时”计数,显示“几乎是最新的”计数 - 例如缓存应用程序中的计数并使值定期到期,以便您更频繁地重新查询计数。或者,如果您将计数存储在每个上面的“统计”表中,您可以拥有一个每小时更新计数的计划作业,而不是每次激活配置文件。

取决于您是否要实时显示确切的数字,或者您是否可以延迟生活。显然,数据量也很重要 - 如果你有一个大型数据库,那么稍微过时的缓存值可能是值得的。

答案 3 :(得分:0)

从纯粹的SQL Server角度来看,不,你不会找到更好的方法来做到这一点。除非,您的社交网络可能是Facebook大小的。对数据设计进行非规范化(例如将计数保存在单独的表中)将导致数据的可能来源不同步。如果编码正确,它不必失去同步,但它可以......

只需确保您有状态索引。此时SQL不会扫描表中的计数,但它会扫描索引。索引将小得多(也就是说,更多数据将适合磁盘页面)。如果要将状态转换为int,smallint或tinyint,则会在磁盘页面中获得更多的索引,因此IO更少。要获取您的描述('激活'等),请使用参考表。参考表会很小,SQL会在第一次访问后将整个内容保存在RAM中。

现在,如果你仍然认为这是太多的开销(并且不应该),你可以想出混合方法。您可以将计数存储在一个单独的表中(如果只是一条记录,SQL将保留在RAM中)或假设您的站点位于asp.net中,您可以创建一个Application变量来跟踪计数。您可以在Session_Start中递增它并在Session_End中递减它。但是,你必须想出一种方法来使增量和减量线程安全,这样两个会话就不会尝试同时更新值。

答案 4 :(得分:0)

您也可以使用Global Temporary table。您将始终获得快速检索。甚至 如果你设置30秒ping。 Example Trigger Link1Example Trigger Link2将在此表中维护此类活动。