0

这是问题所在。

在我最近接管的一个网站上,它跟踪你一天跑的“英里”。因此,用户可以登录该站点,并添加他们跑了 5 英里。然后将其添加到数据库中。

在一天结束时,凌晨 1 点左右,运行一项服务,该服务计算所有里程,所有用户在一天中运行,并将一个文本文件输出到 App_Data。然后,该文本文件会以闪存的形式显示在主页上。

我觉得这有点荒谬。有人告诉我,由于存在大量性能问题,他们必须这样做。他们不会确切地告诉我他们以前是怎么做的,或者主要的性能问题是什么。

那你们会采取什么方法呢?我首先想到的是一个通过 AJAX 调用获取数据的 Web 服务。也许每次添加一个新的“英里”条目时,都会触发一个触发器并更新“GlobalMiles”表。

我将不胜感激有关此的任何信息或提示。

非常感谢!

4

3 回答 3

1

如果由于对数据库的多次访问而导致它们确实存在性能问题,那么我建议您将所有输入都放入消息队列 (MSMQ) 中。然后你可以在另一端有一个服务来接收消息并批量插入数据。这样你就有更少的数据库命中。然后您也可以在更新时输出到文本文件。

于 2009-07-02T02:40:55.827 回答
1

我会创建一个汇总表,每小时或每晚汇总一次,计算总里程数。对于单个请求,您可以从每晚汇总表中提取最后一次汇总计算和用户查看页面之间的任何额外记录里程以获得该用户的总数。

你说的是多少用户,每天有多少日志记录?

于 2009-07-02T02:55:33.067 回答
1

回答这个问题有点困难,因为我们不知道您的所有要求,而且有些东西以前没有用。所以这里有一些不同的想法。

首先,重新审视你的假设。如果您只需要每日报告,那么每天生成一份静态报告是一个非常有效的解决方案。如果只需要一个快照,为什么要在一天中多次访问数据库(例如,许多博客软件在发布博客时用于编写 html 文件,而不是每次都从数据库中提供条目 - 许多人仍然这样做作为优化)。您要添加“实时”功能吗?

我不会马上跳到 AJAX。使用相同的输入法,只是将报表从静态移动到动态。一次做太多事情是埋葬自己的好方法。在更改现有代码时,我会尝试找到可以单独更改的区域,同时对应用程序的其余部分影响最小。然后,一旦您有了动态报告,您就可以添加 AJAX(请使用渐进增强)。

至于动态报告本身,您有几个选择。

当然你可以只选择 SUM(),但是如果每个用户都有大量的条目,这听起来会导致性能问题。

如果您的数据库支持它,我会考虑使用索引视图(有时称为物化视图)。它应该支持允许快速更新实时总和数据:

CREATE VIEW vw_Miles WITH SCHEMABINDING AS 
SELECT SUM([Count]) AS TotalMiles, 
COUNT_BIG(*) AS [EntryCount],
UserId
FROM Miles
GROUP BY UserID
GO
CREATE UNIQUE CLUSTERED INDEX ix_Miles ON vw_Miles(UserId)

如果开销太大,@jn29098 的解决方案是一次不错的选择。使用计划任务将其汇总。如果每个用户有很多条目,则只能添加上次运行任务时的增量。

UPDATE GlobalMiles SET [TotalMiles] = [TotalMiles] + 
  (SELECT SUM([Count]) 
    FROM Miles 
    WHERE UserId = @id 
      AND EntryDate > @lastTaskRun
    GROUP BY UserId)
WHERE UserId = @id

如果您不关心存储单个条目而只关心总数,您可以即时更新计数:

UPDATE Miles SET [Count] = [Count] + @newCount WHERE UserId = @id

您可以将此方法与添加条目并拥有两个世界的 SPROC 结合使用。

最后,您的触发方法也可以正常工作。它是索引视图的替代方案,您可以自己在表上进行更新,而不是 SQL 自动进行更新。它也类似于上一个选项,您将全局更新移出存储过程并进入触发器。

最后三个选项使处理条目被删除时的情况变得更加困难,尽管如果这不是您的应用程序的一个特性,那么您可能不需要担心这一点。

现在您已经在数据库中获得了具体化的实时数据,现在您可以动态生成报告。然后你可以用 AJAX 添加花式。

于 2009-07-02T03:16:21.403 回答