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%,所以可以这样做’等等?
I can tell new developers that these structures are not normalized,
but they can say its faster. How do I counter that? Do I counter that?
Do others structure their databases like this?!
它可能更快,但不一定如此:每当您决定向表中添加额外信息时(在您的情况下为额外字段),您还会增加性能损失,因为表变大,这可能意味着更多数据来自服务器到客户端,或者被分页在内存中或从内存中分页…如果该字段用于加速查询,它可能会有一个或多个索引,这在更新和插入期间也会有性能损失.
不过,主要观点是我在评论中暗示的那个:“缓存”和“预先计算”的值使得系统在数据完整性方面更加脆弱.
你确定“event_creator_id”始终正确指向真正的创作者,即使有人修改了原始值吗?如果是的话,这也有成本,无论是在计算方面(你必须在更改创建者时更新所有表),还是在实际开发和测试工作方面(你确定没有人忘记将更改传播到预先计算的字段? ).
对于诸如“折扣价”或运行总计等聚合值也是如此……并且更改原始数据可能比更改“事件创建者”信息更频繁.同样,是否有适当的“缓存失效”机制,以确保每当有人完成销售时重新计算总销售额?退货项目怎么样?有人考虑过确保诚信的成本吗?
运行总计和其他派生值应该通过使用视图来实现,以便实际的DBMS引擎执行缓存(如果有的话),谁知道如何正确处理这个问题.
Is there a rule of thumb, or a set of principles which I can use to
say that – ‘oh, it will be slower, but only by 1%, so its okay to do
it this way’, etc?
数据库(或可以说是任何类型的计算系统)应该“首先正确”,以便您可以找到如何使其“足够快,第二”.
交易的速度正确性是您在设计数据库时不应该采取的决定,除非您已经知道时效性被认为比正确性更重要.即您的要求明确指出,可能错误或过时的信息不如响应时间重要.
换句话说:设计具有冗余缓存信息的表是过早优化的另一个例子,应该不惜一切代价避免.
另见this – 特别是答案