需要数据库设计建议 - 查询与其他列

时间:2011-03-22 15:19:42

标签: mysql database-design

我有以下表格:

Customer(customer_id) - 1000 rows (1000 customers)
Invoice(invoice_id, customer_id) - 1000000 rows (1000 invoices per customer)
Charge(charge_id, invoice_id, charge_amount) - 20000000 rows (20 charges per invoice)

现在,我正在尝试使用它的总费用来生成客户的发票。 结果表看起来像这样:

Customer_name | invoice_id | charge_total
    test             1          $1000
    test             2          $1200
    test             3          $900
    ...    

我的问题是,针对此案例的数据库设计的最佳做法是什么? 我正在思考以下两个选项:

  1. 只需通过查询运行所有内容吗?
  2. 在发票表中添加“charge_total”列以节省查询处理时间(快20倍)
  3. 谢谢大家!

7 个答案:

答案 0 :(得分:5)

有两种方法可以看待这个问题。数据库纯粹主义者会说派生或计算的数据是多余的并且违反了第3范式。在编辑数据的事务系统中,这是一个问题,因为规范化会阻止您陷入自相矛盾的数据陷阱。

另一方面,有一种实用的观点认为,一次写入但从未更新的数据无论如何都不会更新和删除异常,因此冗余会占用磁盘空间,但不存在风险。

作为一项规则,我总是首先将数据库设计为规范化,然后在仔细检查竞争风险后,在有限的基础上引入冗余。

答案 1 :(得分:1)

这很难回答 - 你知道你有性能问题吗?我不会优化,除非我真的,真的不得不。 即便如此,我还是会考虑一个“发票归档”表来保存计算值。从逻辑上讲,计算摘要并将其存储在表格中以反映实际开具发票的金额(包括税金,运费等)并没有错。这意味着您可以存储发票数据的存档版本而无需担心。

我不想将它存储在主“发票”表中,除非发票是不可变的 - 你创建它,并且从创建它之时就没有任何变化。如果您有一个业务流程,其中预先创建了发票并且随着时间的推移将项目添加到其中,那么这不起作用。

答案 2 :(得分:0)

这个决定取决于用户速度与数据库中额外复杂性之间的权衡,使您的代码更容易出错。这让我想起了这个讨论:

https://stackoverflow.com/questions/211414/is-premature-optimization-really-the-root-of-all-evil

在您的情况下,由于您已经完成了性能测试,我觉得像您建议的那样对数据库进行非规范化是一件好事。

答案 3 :(得分:0)

您要记住的一件事是,数据的变化频率会影响“charge_total”的价值吗?例如,如果退回某个项目,该费用是否会在以后的日期从发票中扣除?如果事情经常发生变化,那么你必须记住让这些变更事件负责更新“charge_total”字段的开销。

答案 4 :(得分:0)

首先,您应该检查没有额外列的性能是否足够。如果不是,那么,而不是之前(!),你应该检查你的“快20倍”猜测是否真的正确。尝试为您的charge_total添加一个View数据库,并测试数据库系统如何处理该视图。我不太了解MySql,但只要源数据不变,一些现代数据库系统就能够对视图数据进行内部缓存。

如果您已经完成了这项工作,而且您确定附加列charge_total是您真正遇到的问题的解决方案,那么您应该确保这些冗余数据保持一致。您可以在数据库端(使用触发器)或在客户端执行此操作 - 当您拥有一个只更改您控制下的charges表的过程时。

答案 5 :(得分:-1)

charge_total表中创建invoice计算列可能是我能想到的最简单的方法。每次运行查询以获取值时,它都可以帮助您避免执行该计算,我假设更频繁地添加费用。

答案 6 :(得分:-3)

现在磁盘空间很便宜,所以你不必担心尺寸。如果额外的列提高了性能,那就去吧。