0

我有一个维护系统性能数据的表,每条记录都是对某个重要方法的调用,由方法名称、其持续时间和一个令牌组成——对系统的每个请求都被赋予一个唯一的令牌,所以所有的具有相同令牌的记录是相同的请求,例如:

CallName    Duration    Token
----------- ----------- -----------
GetData     121         12345
Process     800         12345
SaveData    87          12345

GetData     97          ABCDE
Process     652         ABCDE
SaveData    101         ABCDE

我对按 Token 和 CallName 分组的聚合数据感兴趣,例如:

-- The total duration of each request, in descending order
SELECT Token, SUM(Duration) FROM Requests GROUP BY Token ORDER BY SUM(Duration) DESC

-- The average duration of each call, in descending order
SELECT CallName, AVG(Duration) FROM Requests GROUP BY CallName ORDER BY AVG(Duration) DESC

现在这个表可能非常大,我只会对每个查询的前几条记录感兴趣,所以我已经为这两个查询实现了分页。问题在于,因为这些查询涉及聚合函数,SQL 服务器最终还是会进行表扫描。

其他人以前肯定有过这个问题吗?

我在这里真正需要的是按令牌分组的 SUM(Duration) 上的“索引”,即我可以在其中执行以下操作的表:

SELECT Token, SumToken FROM RequestTokens ORDER BY SumToken DESC
  • 这真的是个坏主意吗?
  • 如果是这样,有没有更好的方法?
  • 最好的方法是什么?INSERT / UPDATE / DELETE 上的触发器会起作用(我根据旧值和更改的数据更新聚合值),还是在更新此表时手动更新我的“索引”会更好?

触发器是迄今为止我想出的最好的解决方案,但我已经看到这是一个死锁/一致性的噩梦!:-S

4

3 回答 3

3

可能是基于聚合的视图,甚至可能是索引视图。我对索引视图做的不多,但本文讨论了将它们与复杂的聚合(如 AVG())一起使用。也许它会让你朝着正确的方向前进。

http://msdn.microsoft.com/en-us/library/aa933148%28SQL.80%29.aspx

于 2009-09-21T14:01:04.740 回答
0

首先,Token 列上的索引是否足够?这样,给定 Token 值,SQL 查询优化器将只扫描包含您感兴趣的行的索引部分。将其设为聚集索引,您将获得最佳性能。

接下来,你怎么知道你有兴趣聚合哪个 Token 值?没有列出日期时间(或时间戳)列,并且 Token 值似乎是随机分配的(而不是某种形式的升序值),所以我猜您在发出查询之前知道要聚合的 Token 值--在哪个索引应该做你想做的事。如果值未知但以某种方式上升,则可以使用多种策略来首先确定最新的 X 令牌值,一旦获得该/那些令牌,您将返回部分表扫描。

于 2009-09-21T13:49:55.313 回答
0

既然我对它有了更好的理解,我将对此进行另一次尝试。这是导致数据仓库解决方案的常见报告问题,如下所示:您可以添加包含预聚合数据的第二个表吗?这确实是非规范化/冗余数据......但它看起来清晰且定义明确,并且可以满足业务需求。这个想法有几个皱纹:

如果数据只输入一次,您是否可以修改数据输入例程以同时添加聚合行。如果它随着时间流逝,你需要重复的过程来“扫除”。我根据一般原则避免触发;它们在这里可能会有所帮助,但它们也可能会根据使用模式和数据相互关系占用您的系统。

数据必须保持多长时间?聚合数据是否与详细数据不同步?如果是,多长时间?您可以设置一个每天/每小时/5 分钟运行的 SQL 代理作业,以扫描最近的条目并更新聚合表。(添加索引的“最后输入”列,这些更新可能会很快。)权衡是您的数据将关闭的时间段。(但该日期时间列可能表示数据准确的“截止时间”。也许您不会在该时间点之后提供聚合数据?)

If the data does not change once it is entered (no updates, no deletes, no late-arriving rows), this could work -- but if you have to maintain updates over time, and the aggregated data changes had to be available at the same time as the data is entered, it could be a nightmare to maintain.

于 2009-09-22T14:13:35.430 回答