重点在于反模式的回答。实际开发中,不会严格遵照三范式。数据库
数据库范式是为解决关系数据库中数据冗余、更新异常、插入异常、删除异常问题而引入的。简单的理解,数据库范式能够避免数据冗余,减小数据库的空间,而且减轻维护数据完整性的麻烦。缓存
第一范式,强调属性的原子性约束,要求属性具备原子性,不可再分解。数据库设计
举个例子,活动表(活动编码,活动名称,活动地址),假设这个场景中,活动地址能够细分为国家、省份、城市、市区、位置,那么就没有达到第一范式。性能
第二范式,强调记录的惟一性约束,表必须有一个主键,而且没有包含在主键中的列必须彻底依赖于主键,而不能只依赖于主键的一部分。编码
举个例子,版本表(版本编码,版本名称,产品编码,产品名称),其中主键是(版本编码,产品编码),这个场景中,数据库设计并不符合第二范式,由于产品名称只依赖于产品编码。存在部分依赖。因此,为了使其知足第二范式,能够改形成两个表:版本表(版本编码,产品编码)和产品表(产品编码,产品名称)。设计
第三范式,强调属性冗余性的约束,即非主键列必须直接依赖于主键。排序
举个例子,订单表(订单编码,顾客编码,顾客名称),其中主键是(订单编码),这个场景中,顾客编码、顾客名称都彻底依赖于主键,所以符合第二范式,可是顾客名称依赖于顾客编码,从而间接依赖于主键,因此不能知足第三范式。为了使其知足第三范式,能够拆分两个表:订单表(订单编码,顾客编码)和顾客表(顾客编码,顾客名称),拆分后的数据库设计,就能够彻底知足第三范式的要求了。索引
值得注意的是,第二范式的侧重点是非主键列是否彻底依赖于主键,仍是依赖于主键的一部分。第三范式的侧重点是非主键列是直接依赖于主键,仍是直接依赖于非主键列。开发
范式能够避免数据冗余,减小数据库的空间,减轻维护数据完整性的麻烦。文档
然而,经过数据库范式化设计,将致使数据库业务涉及的表变多,而且可能须要将涉及的业务表进行多表链接查询,这样将致使性能变差,且不利于分库分表。所以,出于性能优先的考量,可能在数据库的结构中须要使用反模式的设计,即空间换取时间,采起数据冗余的方式避免表之间的关联查询。至于数据一致性问题,由于难以知足数据强一致性,通常状况下,使存储数据尽量达到用户一致,保证系统通过一段较短的时间的自我恢复和修正,数据最终达到一致。
须要谨慎使用反模式设计数据库。通常状况下,尽量使用范式化的数据库设计,由于范式化的数据库设计能让产品更加灵活,而且能在数据库层保持数据完整性。
有的时候,提高性能最好的方法是在同一表中保存冗余数据,若是能允许少许的脏数据,建立一张彻底独立的汇总表或缓存表是很是好的方法。举个例子,设计一张“下载次数表”来缓存下载次数信息,可以使在海量数据的状况下,提升查询总数信息的速度。
另一个比较典型的场景,出于扩展性考虑,可能会使用 BLOB 和 TEXT 类型的列存储 JSON 结构的数据,这样的好处在于能够在任什么时候候,将新的属性添加到这个字段中,而不须要更改表结构。可是,这个设计的缺点也比较明显,就是须要获取整个字段内容进行解码来获取指定的属性,而且没法进行索引、排序、聚合等操做。所以,若是须要考虑更加复杂的使用场景,更加建议使用 MongoDB 这样的文档型数据库。