如何保存汇总多个表的准确记录?

时间:2009-06-04 10:05:44

标签: sql algorithm sqlite normalization

我有一个规范化的数据库,需要经常生成涉及跨多个表连接的基于Web的报告。这些查询耗时太长,所以我想保持计算结果,以便我可以快速加载页面。我总结的表格经常更新,我需要摘要来反映到目前为止的所有更新。

所有表都有自动增量主整数键,我几乎总是添加新行,并可以安排清除计算结果。

我找到了一个类似的问题,我需要通过对表中的每一行进行迭代来迭代单个表,并跟踪迭代器状态和最高主要敏锐度(即“高水位”)。对于单个表来说这很好,但对于多个表,我最终会保留每个表的一个高水值,这感觉很复杂。或者,我可以对一个表进行非规范化(具有相当广泛的应用程序更改),感觉向后退一步,可能会将我的数据库大小从大约5GB更改为大约20GB。

(我目前正在使用sqlite3,但MySQL也是一种选择)。

5 个答案:

答案 0 :(得分:2)

我看到两种方法:

  1. 您将数据移动到一个单独的数据库中,非规范化,进行一些预先计算,以优化它以便快速访问和报告(听起来像一个小型数据仓库)。这意味着您必须考虑将数据从源复制并转换为目标的一些作业(脚本,单独的应用程序等)。根据您希望完成复制的方式(完整/增量),复制频率和数据模型(源和目标)的复杂性,可能需要一段时间才能实现,然后优化过程。它的优势在于保持源数据库不变。

  2. 保留当前数据库,但是对其进行非规范化。正如你所说,这可能意味着改变了应用程序的逻辑(但你可能会找到一种方法来最小化使用数据库对逻辑的影响,你知道情况比我好:))。

答案 1 :(得分:1)

您可以创建触发器。

只要其中一个计算值发生变化,您就可以执行以下操作之一:

  • 更新计算字段(首选)
  • 重新计算摘要表
  • 存储需要重新计算的标志。下次需要计算值时,首先检查此标志并在必要时进行重新计算

示例:

CREATE TRIGGER update_summary_table UPDATE OF order_value ON orders 
BEGIN
  UPDATE summary 
    SET total_order_value = total_order_value 
                          - old.order_value 
                          + new.order_value 
    // OR: Do a complete recalculation
    // OR: Store a flag
END;

有关SQLite触发器的更多信息:http://www.sqlite.org/lang_createtrigger.html

答案 2 :(得分:1)

报告是否可以逐步刷新,还是完全重新计算以重新编写报告?如果它必须是完全重新计算,那么您基本上只想缓存结果集,直到需要下一次刷新。您可以创建一些表来包含报告输出(以及元数据表以定义可用的报告输出版本),但大多数情况下这是过度的,您最好将查询结果保存到文件或其他缓存存储中

如果是增量刷新,那么无论如何都需要PK范围,所以你需要像你的高水位数据(除了你可能想要存储最小/最大对)。

答案 3 :(得分:0)

最后,我安排了一个程序实例来进行所有数据库更新,并在其堆中维护摘要,即根本不在数据库中。在这种情况下,这非常好用,但如果我有多个程序在进行数据库更新,则会不合适。

答案 4 :(得分:0)

您还没有说过您的索引策略。我先看一下 - 确保你的索引覆盖。

然后我认为所讨论的触发选项也是一个非常好的策略。

另一种可能性是数据仓库的常规人口,其模型适合高性能报告(例如,Kimball模型)。