id
名称
客户
id
id_project
名称
付款
id
id_customer
sum
当用户进入系统时,他将拥有访问某个项目。现在,我想列出该项目的所有付款,这应该很简单:
SELECT FROM payments where id_customer in (SELECT id from customers where id_project = 5)
我的问题是:添加一个更好将id_project列到付款表,这样查询将变得更加轻松快捷。
#1 楼
似乎您在问反规范化是否有意义。反规范化是尝试通过添加冗余数据或对数据进行分组来优化数据库读取性能的过程。在某些情况下,非规范化有助于弥补关系数据库软件固有的效率低下的问题。关系规范化数据库即使对数据进行了物理调优以实现高性能,也对数据的物理存储造成了沉重的访问负担。
答案始终是“取决于”的,所以这是我的规则thumb:
如果...
数据量不大
您还没有进行大量的联接
和/或数据库性能当前不是瓶颈,然后保持正常状态。是的,非规范化速度更快,但这也意味着系统中存在冗余数据,这些数据必须维护并保持同步。该数据不再有“一个来源”,而是可以偏离的多个来源。随着时间的流逝,这是有风险的,因此,除非有充分的理由去做,否则您就不应该这样做,并且要有一些基准支持。
我只会在...
/>
数据量非常大
联接很昂贵,您必须执行很多操作才能返回简单的查询
数据库性能是瓶颈和/或您想尽可能快地运行
在现代硬件上联接非常快,但它们从来都不是免费的。
#2 楼
您最好将查询改写为: -query作为上面的联接,相反,一个糟糕的查询计划者可能最终会进行payments.id_customer
的索引扫描(假设您有相关的索引)(或更糟糕的是,表扫描),而不是以更有效的方式进行操作。如果此查询的安排包含在更复杂的内容中,那么即使是好的查询计划者也可能看不到优化。将关系表示为联接而不是子查询可能比更改数据结构有更多不同。正如Jeff所说,任何非规范化都应谨慎考虑-可以轻松提高性能,特别是出于某些报告目的,但由于支持业务逻辑中的错误而可能导致不一致。关系对我来说似乎很奇怪。它们暗示您不能与同一客户有多个项目,这在我的经验中通常是不正确的,至少在很长一段时间内都是如此。
SELECT payments.*
FROM customers
JOIN payments
ON payments.id_customer = customers.id
WHERE customers.id_project = 5
标准化程度较低(尽管我怀疑这样做是否必要): >
评论
性能的第一原则:切勿在生产中使用*!
–布赖恩·鲍尔森-斯坦顿(Brian Ballsun-Stanton)
2011年1月10日上午10:35
@布莱恩:非常有效的一点。并且,如果sys.depends由于使用DROP VIEW + CREATE VIEW而不是ALTER VIEW而被淘汰,那么在select子句中避免*以及潜在的性能隐患也可以避免MSSQL视图中的列排序问题。
– David Spillett
2011年1月10日上午10:43
@Brian我写了*以便于写作。
–加百列·所罗门
2011年1月10日上午11:03
该项目被认为是具有其域上的一个独立应用程序,并且属于不同的客户,因此客户不能在不同的项目上拥有相同的帐户
–加百列·所罗门
2011年1月10日,11:05
评论
因此对于现代RDBMS(或更好的是,使用join),查询不是问题。同意,获取有关subselect vs join的查询计划,并查看哪个更好。
我认为这篇SO帖子值得一看,因为@igor提到使用JOIN或IN