我有这些表:
Projects(projectID, CreatedByID) Employees(empID,depID) Departments(depID,OfficeID) Offices(officeID)
CreatedByID
是一个外键的Employees
.我有一个几乎每个页面加载运行的查询.
添加冗余OfficeID
列Projects
以消除三个连接是不好的做法吗?或者我应该做以下事情:
SELECT * FROM Projects P JOIN Employees E ON P.CreatedBY = E.EmpID JOIN Departments D ON E.DepID = D.DepID JOIN Offices O ON D.officeID = O.officeID WHERE O.officeID = @SomeOfficeID
在应用程序编程中,我"首先编写最佳实践并在之后进行优化",但数据库管理员始终警告连接的成本.
归一化直到它疼,然后去归一化直到它起作用
非规范化具有快速SELECT
查询大型查询的优点.
缺点是:
需要更多的编码和时间来确保完整性(在您的情况下这是最重要的)
DML上的速度较慢(INSERT/UPDATE/DELETE)
它需要更多空间
至于优化,您可以优化更快的查询或更快的DML(通常,这两个是拮抗剂).
优化快速查询通常意味着重复数据,无论是非规范化,索引,还是额外的表格.
如果是索引,RDBMS会为您执行此操作,但在非规范化的情况下,您需要自己编写代码.如果Department
转移到另一个Office
怎么办?你需要在三个表而不是一个表中修复它.
所以,正如我从你的表名中看到的那样,那里不会有数百万条记录.因此,您最好将数据规范化,管理起来会更简单.
始终在必要时进行规范化以消除数据库完整性问题(即潜在的重复或丢失数据).
即使非正规化带来了性能提升(通常情况并非如此),但丢失数据完整性的代价太高而无法证明其合理性.
只要问一下那些不得不努力解决遗留数据库中所有模糊问题的人,无论他们喜欢好的数据还是无关紧要的(如果有的话)速度提升.
此外,如John所述 - 如果您最终需要非规范化数据(用于速度/报告/等),则在单独的表中创建它,保留原始数据.
连接的成本本身不应该太担心(除非你试图扩展到数百万用户,在这种情况下你绝对应该担心).
我会更关心对调用它的代码的影响.规范化数据库更容易编程,并且几乎总是在应用程序本身内提高效率.
也就是说,不要超越理性的范围.我已经看到了规范化的规范化,它通常最终出现在一个数据库中,该数据库有一个或两个实际数据表,而20个表只填充了外键.这显然是矫枉过正的.我通常使用的规则是:如果列中的数据会以其他方式重复,则应对其进行规范化.