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

Sql 在数据库上创建变量以保存全局统计信息,sql,sql-server,sql-server-2005,variables,Sql,Sql Server,Sql Server 2005,Variables,让我们假设我有一个社交网络。 我总是向用户显示有多少用户注册并激活了他们的个人资料。 因此,每次单个用户登录时,它都会转到DB并进行以下操作: select count(*) from users where status = 'activated' 因此,如果有5000个用户登录,或者只是刷新页面,它将向上面的SQL发出5000个请求。 我想知道是否最好在某个地方设置一个变量(我仍然不知道该放在哪里),每当用户激活其个人资料时,该变量将添加1,然后,当我想显示有多少用户注册到该社交网络时,我

让我们假设我有一个社交网络。 我总是向用户显示有多少用户注册并激活了他们的个人资料。 因此,每次单个用户登录时,它都会转到DB并进行以下操作:

select count(*) from users where status = 'activated'
因此,如果有5000个用户登录,或者只是刷新页面,它将向上面的SQL发出5000个请求。 我想知道是否最好在某个地方设置一个变量(我仍然不知道该放在哪里),每当用户激活其个人资料时,该变量将添加1,然后,当我想显示有多少用户注册到该社交网络时,我只会得到该变量的值


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

您可以考虑以下几个选项:

1) 就像您所说的,每次激活配置文件时都要维护一个全局计数,以保存每次对用户表的点击。您可以将该计数存储在“Stats”表中,然后从中查询该值

2) 不要显示实际的“实时”计数,而是显示一个“几乎是最新的”计数-例如,在应用程序中缓存该计数,并让该值定期过期,这样您就可以减少重新查询计数的频率。或者,如果您将计数存储在上面的“Stats”表中,您可以有一个每小时更新计数的计划作业,而不是每次激活配置文件时更新计数


这取决于您是想实时显示准确的数字,还是可以忍受延迟。显然,数据量也很重要-如果您有一个大型数据库,那么有一个稍微过时的缓存值可能是值得的。

正如您已经猜到的-每次有人访问站点时计算这个值不是一个好主意

您可以按照您的建议执行操作,并在添加用户时更新中心值,不过您必须确保不会出现两个进程同时更新数字的情况

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


或者#2,您可以使用MemCache之类的工具将计算值保留一段时间,然后当缓存过期时,重新计算它。

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

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

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

您也可以使用。你总是能得到快速检索。即使
如果设置为30秒ping。将在此表中维护此类活动。

您可以使用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
而且它不必查询基础表。您需要在下面的版本(企业/开发人员)中使用
和(NOEXPAND)
提示



尽管正如@Jim所建议的,当索引列可以使用相等比较满足查询条件时,对索引进行计数(*)也应该很快。

这就是我想知道的,哈哈哈,我会创建一个表来只存储这个?为了更新这个值,我会做一个触发器?我以前从未这样做过。是的,根据您想要预计算的其他值,您可以创建一个带有
名称
列的
统计数据
全局数据
表,这样您就可以存储
名称class='USERS'
值=XXX
,或者如果您只想存储一些值,您可以有一个包含单行的表,每个值都有字段。例如,如果我每30秒进行一次计数(*),并将该计数列存储在表中,会怎么样?它永远不会有与其他任何东西冲突的问题。事实上,这就是他们想要我做的事。@pringlesinn:是的,那会管用的。这永远只是一个估计,但如果这就是你想要的,它是有效的。这不是同样的事情吗?无论如何,我必须选择5000个选项来查看它。如果我错了,不要责怪我,但对我来说也是一样的:(@pringlesinn-如果你想把这些信息保存在SQL Server中,这是最简单的事情。或者要扭转你的查询,把它保存在“某个地方的变量”中不是吗需要5000个该变量的查询?如果您不想对数据库运行任何查询,请将最新的数据保留在应用程序缓存中,但不要指望SQL为您维护它。我希望每30秒更新一次完整的select count blah blah blah blah,更新单个列上的值