.net 计算列,或按触发器更新列以保留统计信息

.net 计算列,或按触发器更新列以保留统计信息,.net,sql-server,calculated-columns,.net,Sql Server,Calculated Columns,对于每个用户,我们的应用程序都会计算一些统计数据,比如他们登录了多少次,或者他们在测验中答错了多少个答案。。。它可以是各种各样的东西。该应用程序在SQL Server和.NET Entity Framework 6.1上运行 目前,统计数据是按需计算的,但随着用户基数的增加,这使得应用程序的报告部分变得越来越慢 我们想知道是使用计算列(持久化还是非持久化)还是使用触发器与用户存储这些值 你打算怎么做?在我看来,计算列可能更容易实现,但每次我从表中读取用户时,它们都会被重新计算,这可能不会比我们现

对于每个用户,我们的应用程序都会计算一些统计数据,比如他们登录了多少次,或者他们在测验中答错了多少个答案。。。它可以是各种各样的东西。该应用程序在SQL Server和.NET Entity Framework 6.1上运行

目前,统计数据是按需计算的,但随着用户基数的增加,这使得应用程序的报告部分变得越来越慢

我们想知道是使用计算列(持久化还是非持久化)还是使用触发器与用户存储这些值

你打算怎么做?在我看来,计算列可能更容易实现,但每次我从表中读取用户时,它们都会被重新计算,这可能不会比我们现在所做的快很多。因为我们会将整个SQL查询放入计算列,所以持久化该列似乎也不合适(SQL Server将如何推断它应该更新计算?)。 对我来说,触发某些行为似乎更符合逻辑

对于参数而言,假设所有计算的统计信息都是其他表中值的
count(*)和
sum(*)和
sum(*),没有什么比这更有趣的了。

如果必须存储计算值,最好让SQL引擎为您完成工作,而不是通过触发器手动实现

因此,这将是持久的和/或

每次我从表中读取用户时,它们都会被重新计算

仅当您在
选择中包含计算列时(并且您没有选择将其持久化)。这就是为什么查询通常应该只查询所需的列,而不是
select*
。但是,由于您使用的是ORM,您可能无法告诉它不要包含昂贵的列—这就是为什么您应该更喜欢持久性或使用索引视图—以便将其视为单独的对象,仅在需要时加载

SQL Server将如何推断它应该更新计算

因为在幕后,SQLServer有效地实现了触发器本身。但这里的好处是,这些触发器已经被测试了数百万次,并且是您不必编写的代码

为了说明此参数,假设所有计算的统计信息都是其他表中值的
count(*)
sum(*)

在这种情况下,您不能真正使用计算列路径(计算列应该只引用自己表中自己的行。有一些奇怪的方法可以尝试使用UDF绕过这一点,但我通常不建议这样做),因此在这种情况下,我肯定会推荐索引视图

对于参数,假设所有计算的统计信息都是count()和sum()值,没有比这更有趣的了

由于您的报告操作非常简单,因此我建议为这些统计信息创建一个报告表/审计日志表

基本前提是,所有报告都可以作为简单查询的变体获得,如

SELECT COUNT(*) FROM tblUserLog (NO LOCK) WHERE UserID=34
SELECT 
  COUNT(*) OVER(PARTITION BY colA ORDER BY colB) as Metric1, 
  SUM(*) OVER (PARTITION BY colD ORDER BY colC) as Metric2
FROM tblUserLog (NO LOCK) WHERE UserID =34
或者在一个稍微复杂的查询中,如

SELECT COUNT(*) FROM tblUserLog (NO LOCK) WHERE UserID=34
SELECT 
  COUNT(*) OVER(PARTITION BY colA ORDER BY colB) as Metric1, 
  SUM(*) OVER (PARTITION BY colD ORDER BY colC) as Metric2
FROM tblUserLog (NO LOCK) WHERE UserID =34
现在的主要问题是如何填充此表
tblUserLog
应该是什么组成

作文

表的架构应该是通用的,并且必须满足您的所有报告需求,例如要计算或求和的列。说些与事实相符的话

LogID (PK, auto increment)
LogDateTimestamp
LogType
UserID
MetricToSum1
MetricToSum2
....
这是一个非标准化的表;我不建议将其正常化

如何填充:

这绝对不应该通过触发器来完成。寻找最佳备选方案,并假设您的web应用程序具有良好的分层体系结构;您应该有一个日志方法,它可以异步地将必要的详细信息插入DB表中。因此,在表上的写入基本上与主用户表CRUD和按需读取同步进行 无论何时需要报告


对于一个非常简单的操作,我建议您只需在主实体表上实现一个视图,如User。这类视图的一个示例是返回管理员报告的活动用户数。

他们登录的次数:这是一个不断变化的数字,而他们在测验中出错的答案数量在“测验”完成后似乎是一个静态数字。所以你真的有两种非常不同的情况,可能需要不同的方法。嘿,谢谢你的评论,但它们只是两个愚蠢的例子。事实上,它们都是不断变化的数字。