标题没有太大意义,但我想不出更好的标题来解决这个问题。
我有以下表格
项目
- ID
- 姓名
顾客
- ID
- id_project
- 姓名
付款
- ID
- id_customer
- 日期
- 和
当用户进入系统时,他将有权访问某个项目。现在,我想列出该项目的所有付款,这应该很容易:
SELECT FROM payments where id_customer in (SELECT id from customers where id_project = 5)
我的问题是:如果以这种方式将列 id_project 添加到支付表中不是更好,那么查询将更容易和更快。
您似乎在问非规范化是否有意义。
答案总是“视情况而定”,所以这是我的经验法则:
如果 ...
然后保持正常化。是的,非规范化更快,但这也意味着系统中有冗余数据——必须维护并保持同步的数据。该数据不再有“一个来源”,而是可以偏离的多个来源。随着时间的推移,这是有风险的,所以你不应该这样做,除非你有很好的理由这样做,并得到一些基准的支持。
我只会在......
连接在现代硬件上非常快,但它们从来都不是免费的。
您最好将查询重写为:
虽然这看起来不那么简洁,一个好的查询规划器会看到你正在尝试做的事情并运行你的相关子查询作为上面的连接,一个糟糕的查询规划器最终可能会进行索引扫描
payments.id_customer
(假设你有一个相关的索引)(或更糟糕的是,表格扫描)而不是以更有效的方式做事。如果这个查询的安排包含在更复杂的东西中,即使是一个好的查询计划器也可能看不到优化。将关系表达为连接而不是子查询可能比更改数据结构产生更大的不同。正如 Jeff 所说,任何非规范化都应该谨慎考虑——它可以带来简单的性能提升,特别是对于某些报告目的,但可能由于支持业务逻辑中的错误而导致不一致。
作为旁注:显然我不了解您的业务,所以我可能会遗漏一些东西,但是您的餐桌关系对我来说似乎很奇怪。他们暗示你永远不能与同一个客户拥有一个以上的项目,这在我的经验中通常是不正确的,至少在很长一段时间内是这样。
或者如果标准化程度较低(尽管我怀疑这是必要的):
当然,这仍然会降低与两个客户合作项目的可能性……
在某些数据库中,您可以基于复杂查询创建“物化视图”而不是具有大量数据的复杂视图。这可用于避免历史增长的应用程序系统中的非规范化。如果您决定使用“物化视图”您必须清楚地了解刷新方法和物化视图将使用的存储量......