数据库是否应该应用外键的一点思考
2015-07-21 10:58
447 查看
最近看了和尚师傅的数据库设计。数据库表都是孤立的,不存在外键关系。虽然放弃了EF引以为傲的懒加载和导航属性等特性,实际编码量也会增大。但是带来的优点是灵活性非常高。表和表之间没有任何约束。当然这点也可以认为是缺点。
我一直以为这种设计在互联网场景下比较适合。企业内部相对不变的管理系统可以使用主外键来提高开发速度,减少代码量。最近一个系统在上线之初就遇到了很大的分歧。用户几乎想全盘推翻我们的设计,这个时候,想要重新设计就显得非常困难,需要修改数据库结构才能达到。
外键是什么?
在这里,外键其实是业务关系的一种映射。而且这种映射是硬编码的。改动起来非常困难,牵一发而动全身。一旦业务需求发生改变。外键的副作用是灾难性的。相比之下,外键结合EF带来的一点编码的方便性简直可以忽略不计。和尚师傅教育的很对,不要使用任何外键,外键就是实体键硬编码的关系。这种关系往往对应着业务逻辑。
外键是必须的吗?
我们使用外键的另一个目的就是依赖数据库来强制维护数据的完整性。说到底就是对业务逻辑层的数据维护不放心。怕破坏了数据的完整性。其实只要静心编写,认真测试。业务逻辑层的可靠性是非常高的。在一般场景中是完全可以接受的。退一万步说,即时出现了碎片数据。我们也可以通过种种手段去清除碎片数据。在不影响系统的前提下,其实都不必理会这些碎片。
使用外键是对ORM工具的依赖
使用外键,往往以为着对ORM某些特性的依赖。从而使得持久层和DAL层之间产生了某种紧耦合。比如外键在EF中被映射为导航属性,我们可以依托泛型编程来非常方便的进行联查和筛选。如果有一天抛开ORM工具。使用SQL语句来进行读写。这点点优点也消失不见了。
结论:在小型团队,缺乏专业DBA的情况下。不使用外键,仅仅将数据库作为“库”,而避免使用关系。这样依赖,一些数据实体就变得非常单纯,只是客观对象的映射,和业务没有丝毫的关系。我们可以围绕数据实体来灵活的构建业务所需要的表。即时用户的需求发生变化。我们的核心“数据实体"是不会变化的,变化的只是外围的业务表。变更起来更为灵活。
举个栗子,如果开发一个“成绩管理系统”,学生和班级是多对一关系。那么我们是否应该在学生表中设计班级主键呢?在学生表中设计班级主键是非常常见的做法。但是这样会破坏“学生”实体的纯洁性。班级并不是学生的固有属性,我们应该建立一个连接表来保存学生和班级的主键,在外部来维持二者的关系。从而维护核心数据实体的纯洁性。
我一直以为这种设计在互联网场景下比较适合。企业内部相对不变的管理系统可以使用主外键来提高开发速度,减少代码量。最近一个系统在上线之初就遇到了很大的分歧。用户几乎想全盘推翻我们的设计,这个时候,想要重新设计就显得非常困难,需要修改数据库结构才能达到。
外键是什么?
在这里,外键其实是业务关系的一种映射。而且这种映射是硬编码的。改动起来非常困难,牵一发而动全身。一旦业务需求发生改变。外键的副作用是灾难性的。相比之下,外键结合EF带来的一点编码的方便性简直可以忽略不计。和尚师傅教育的很对,不要使用任何外键,外键就是实体键硬编码的关系。这种关系往往对应着业务逻辑。
外键是必须的吗?
我们使用外键的另一个目的就是依赖数据库来强制维护数据的完整性。说到底就是对业务逻辑层的数据维护不放心。怕破坏了数据的完整性。其实只要静心编写,认真测试。业务逻辑层的可靠性是非常高的。在一般场景中是完全可以接受的。退一万步说,即时出现了碎片数据。我们也可以通过种种手段去清除碎片数据。在不影响系统的前提下,其实都不必理会这些碎片。
使用外键是对ORM工具的依赖
使用外键,往往以为着对ORM某些特性的依赖。从而使得持久层和DAL层之间产生了某种紧耦合。比如外键在EF中被映射为导航属性,我们可以依托泛型编程来非常方便的进行联查和筛选。如果有一天抛开ORM工具。使用SQL语句来进行读写。这点点优点也消失不见了。
结论:在小型团队,缺乏专业DBA的情况下。不使用外键,仅仅将数据库作为“库”,而避免使用关系。这样依赖,一些数据实体就变得非常单纯,只是客观对象的映射,和业务没有丝毫的关系。我们可以围绕数据实体来灵活的构建业务所需要的表。即时用户的需求发生变化。我们的核心“数据实体"是不会变化的,变化的只是外围的业务表。变更起来更为灵活。
举个栗子,如果开发一个“成绩管理系统”,学生和班级是多对一关系。那么我们是否应该在学生表中设计班级主键呢?在学生表中设计班级主键是非常常见的做法。但是这样会破坏“学生”实体的纯洁性。班级并不是学生的固有属性,我们应该建立一个连接表来保存学生和班级的主键,在外部来维持二者的关系。从而维护核心数据实体的纯洁性。
相关文章推荐
- 转 -- MySQL主从失败, 错误Got fatal error 1236解决方法
- sqlldr并发
- 转:Redis 在新浪微博中的应用
- 通过数据库向Django模型添加字段的示例
- 关于 MySQL 密码你应该知道的那些事
- Redis的内存碎片
- MySQL修改root账号密码的方法
- sqlserver 分页
- 【2.26】数据库
- LOGGING 、FORCE LOGGING 、NOLOGGING、归档模
- sqlhelper中ConfigurationManager的问题
- SQL Server ->> 生成Numbers辅助表
- mysql not in、left join、IS NULL、NOT EXISTS 效率问题记录
- SQL中 将同一个表中的A列更新到B列,B列更新到A列
- SQL Server 存储过程
- 如何使用SQLite数据库 匹配一个字符串的子串?
- mysql强制索引和禁止某个索引
- 记一次苦逼的Sql查询优化
- mysql修改数据库表的字段
- 机房收费系统之链接篇(SQL Server Error:26 & SQL Server Error:5120)