9

我进退两难了。我正在处理大量遗留代码,并且在表结构中看到大量冗余信息。它们主要以两种形式存在:

A. 要保存在“连接”上的冗余信息。例如:

event_id, event_name, event_creator_id
       3       test1                43

subevent_id, event_id, event_creator_id 
         21         3               43

请注意 event_creator_id 的重复性。以前的“高级”开发人员给出的理由是,当我们需要事件创建者 id 时,我们只需要查询一个表,而不是进行“昂贵的”连接来检索值。

B. 节省计算的冗余信息。例如:

event_id, event_default_price
       3                  100

discount_id, discount_code, discount_percentage
          7,          ABCD,                  50

special_event_id, event_id, discount_id, discounted_price
              21         3            7,               50

请注意,不是为这个特殊事件计算最终的“discounted_price”(因为对 discount_id 的引用已经存在),代码将“计算”值保存在这里。同样,理由是“速度”,常态下地狱。

我有两个问题:

  1. 我可以告诉新开发人员这些结构没有标准化,但他们可以说它更快。我该如何反击?我反对吗?其他人是否像这样构建他们的数据库?!
  2. 有没有一个经验法则或一套原则,我可以用来说 - “哦,它会更慢,但只有 1%,所以可以这样做等等?
4

2 回答 2

18

关于你的两个问题:

我可以告诉新开发人员这些结构没有标准化,但他们可以说它更快。我该如何反击?我反对吗?其他人是否像这样构建他们的数据库?!

它可能更快,但不一定如此:每当您决定向表中添加额外信息(在您的情况下为额外字段)时,您也会增加性能损失,因为表变得更大,这可能意味着更多数据来自服务器到客户端,或者被调入或调出内存......如果该字段用于加速查询,它可能会有一个或多个索引,这在更新和插入期间再次有性能损失。不过,要点是我在评论中暗示的一点:“缓存”和“预计算”值使系统在数据完整性方面更加脆弱。您确定“event_creator_id”始终正确指向真正的创建者,即使有人修改了原始值?如果是,这也有成本,

对于“折扣价”或运行总计等汇总值也是如此……更改原始数据可能比更改“事件创建者”信息更频繁。同样,是否有适当的“缓存失效”机制来确保在有人完成销售时重新计算总销售额?退回的物品怎么办?有没有人考虑过确保完整性的成本?

相反,运行总计和其他派生值应该通过使用视图来实现,以便缓存(如果有)由知道如何正确处理这一点的实际 DBMS 引擎执行。

是否有一个经验法则或一组原则,我可以用来说 - “哦,它会慢一些,但只有 1%,所以可以这样做”等等?

DB(或可以说是任何类型的计算系统)应该“首先正确”,以便您可以找到如何使其“足够快,其次”。以正确性换取速度是您在设计数据库时不应该做出的决定,除非您已经知道及时性被认为比正确性更重要。即您的要求明确指出,拥有可能错误或过时的信息不如响应时间重要。

换句话说:设计一个带有冗余缓存信息的表是过早优化的另一个例子,应该不惜一切代价避免。

另请参阅-特别是答案

于 2012-07-06T11:33:56.610 回答
0

我读过的任何关于关系设计的数据库书籍都包含关于“计划的”冗余或“有限的”反规范化的部分。这取决于环境。Wells Fargo 预先计算银行对账单总额并存储预先计算的数据。

想象一下,如果他们在打印语句时等到每个周期结束时进行这些计算需要多长时间。

计划冗余是正常的!

于 2015-06-11T21:28:06.190 回答