装箱百万奖金,第六届全国工业互联网数据创新应用大赛火热报名中! 了解详情
写点什么

开发人员如何有效地进行数据库设计

  • 2013-04-04
  • 本文字数:2716 字

    阅读完需:约 9 分钟

数据库设计在软件开发过程中占有重要的地位,国内开发者 MeteorSeed 在博客中结合自己的实际经历全面总结了关系型数据库设计需要注意的各个方面,包括Codd 的基本法则、设计阶段、设计原则和命名规则。

MeteorSeed 认为在项目早期应该由开发者进行数据库设计,后期调优则需要 DBA:“一个精通 OOP 和 ORM 的开发者,设计的数据库往往更为合理,更能适应需求的变化”。他引用了关系数据库之父 Codd 的 12 条法则,作为数据库设计的指导性方针:

  1. 信息法则 关系数据库中的所有信息都用唯一的一种方式表示——表中的值。
  2. 保证访问法则 依靠表名、主键值和列名的组合,保证能访问每个数据项。
  3. 空值的系统化处理 支持空值(NULL),以系统化的方式处理空值,空值不依赖于数据类型。
  4. 基于关系模型的动态联机目录 数据库的描述应该是自描述的,在逻辑级别上和普通数据采用同样的表示方式,即数据库必须含有描述该数据库结构的系统表或者数据库描述信息应该包含在用户可以访问的表中。
  5. 统一的数据子语言法则 一个关系数据库系统可以支持几种语言和多种终端使用方式,但必须至少有一种语言,它的语句能够一某种定义良好的语法表示为字符串,并能全面地支持以下所有规则:数据定义、视图定义、数据操作、约束、授权以及事务。(这种语言就是 SQL)
  6. 视图更新法则 所有理论上可以更新的视图也可以由系统更新。
  7. 高级的插入、更新和删除操作 把一个基础关系或派生关系作为单个操作对象处理的能力不仅适应于数据的检索,还适用于数据的插入、修改个删除,即在插入、修改和删除操作中数据行被视作集合。
  8. 数据的物理独立性 不管数据库的数据在存储表示或访问方式上怎么变化,应用程序和终端活动都保持着逻辑上的不变性。
  9. 数据的逻辑独立性 当对表做了理论上不会损害信息的改变时,应用程序和终端活动都会保持逻辑上的不变性。
  10. 数据完整性的独立性 专用于某个关系型数据库的完整性约束必须可以用关系数据库子语言定义,而且可以存储在数据目录中,而非程序中。
  11. 分布独立性 不管数据在物理是否分布式存储,或者任何时候改变分布策略,RDBMS 的数据操纵子语言必须能使应用程序和终端活动保持逻辑上的不变性。
  12. 非破坏性法则 如果一个关系数据库系统支持某种低级(一次处理单个记录)语言,那么这个低级语言不能违反或绕过更高级语言(一次处理多个记录)规定的完整性法则或约束,即用户不能以任何方式违反数据库的约束。

MeteorSeed 把数据库设计阶段分为规划阶段、概念阶段、逻辑阶段、实现阶段和物理阶段。关于设计原则,他从以下几个方面阐述了自己的经验:

  • 降低对数据库功能的依赖 功能应该由程序实现,而非 DB 实现。原因在于,如果功能由 DB 实现时,一旦更换的 DBMS 不如之前的系统强大,不能实现某些功能,这时我们将不得不去修改代码。所以,为了杜绝此类情况的发生,功能应该有程序实现,数据库仅仅负责数据的存储,以达到最低的耦合。

  • 定义实体关系的原则 当定义一个实体与其他实体之间的关系时,需要考量如下:

    • 牵涉到的实体 识别出关系所涉及的所有实体。
    • 所有权 考虑一个实体“拥有”另一个实体的情况。
    • 基数 考量一个实体的实例和另一个实体实例关联的数量。
      关系与表数量
  • 描述 1:1 关系最少需要 1 张表。

  • 描述 1:n 关系最少需要 2 张表。

  • 描述 n:n 关系最少需要 3 张表。

  • 列意味着唯一的值 如果表示坐标(0,0),应该使用两列表示,而不是将“0,0”放在 1 个列中。

  • 列的顺序 列的顺序对于表来说无关紧要,但是从习惯上来说,采用“主键 + 外键 + 实体数据 + 非实体数据”这样的顺序对列进行排序显然能得到比较好的可读性。

  • 定义主键和外键 数据表必须定义主键和外键(如果有外键)。定义主键和外键不仅是 RDBMS 的要求,同时也是开发的要求。几乎所有的代码生成器都需要这些信息来生成常用方法的代码(包括 SQL 文和引用),所以,定义主键和外键在开发阶段是必须的。之所以说在开发阶段是必须的是因为,有不少团队出于性能考虑会在进行大量测试后,在保证参照完整性不会出现大的缺陷后,会删除掉 DB 的所有外键,以达到最优性能。MeteorSeed 认为,在性能没有出现问题时应该保留外键,而即便性能真的出现问题,也应该对 SQL 文进行优化,而非放弃外键约束。

  • 选择键
    人工键与自然键。人工键——实体的非自然属性,根据需要由人强加的,如 GUID,其对实体毫无意义;自然键——实体的自然属性,如身份证编号。人工键的好处:键值永远不变;永远是单列存储。人工键的缺点:因为人工键是没有实际意义的唯一值,所以不能通过人工键来避免重复行。MeteorSeed 建议全部使用人工键。原因如下:

  • 在设计阶段我们无法预测到代码真正需要的值,所以干脆放弃猜测键,而使用人工键。

  • 人工键复杂处理实体关系,而不负责任何属性描述,这样的设计使得实体关系与实体内容得到高度解耦,这样做的设计思路更加清晰。

MeteorSeed 的另一个建议是——每张表都需要有一个对用户而言有意义的自然键,在特殊情况下也许找不到这样一个项,此时可以使用复合键。这个键我在程序中并不会使用其作为唯一标识,但是却可以在对数据库直接进行查询时使用。使用人工键的另一个弊端,主要源自对查询性能的考量,因此选择人工键的形式(列的类型)很重要:

  • 自增值类型,由于类型轻巧查询效率更好,但取值有限。
  • GUID 查询效率不如值类型,但是取值无限,且对开发人员更加亲切。

智能健与非智能键。智能键——键值包含额外信息,其根据某种约定好的编码规范进行编码,从键值本身可以获取某些信息;非智能键,单纯的无意义键值,如自增的数字或 GUID。智能键是一把双刃剑,开发人员偏爱这种包含信息的键值,程序盼望着其中潜在的数据;数据库管理员或者设计者则讨厌这种智能键,原因也是很显然的,智能键对数据库是潜在的风险。前面提到,数据库设计的原则之一是不要把具有独立意义的值的组合实现到一个单一的列中,应该使用多个独立的列。数据库设计者,更希望开发人员通过拼接多个列来得到智能键,即以复合主键的形式给开发人员使用,而不是将一个列的值分解后使用。开发人员应该接受这种数据库设计,但是很多开发者却想不明白两者的优略。MeteorSeed 认为,使用单一列实现智能键存在这样一个风险,就是我们可能在设计阶段无法预期到编码规则可能会在后期发生变化。比如,构成智能键的局部键的值用完而引起规则变化或者长度变化,这种编码规则的变化对于程序的有效性验证与智能键解析是破坏性的,这是系统运维人员最不希望看到的。所以 MeteorSeed 建议如果需要智能键,请在业务逻辑层封装(使用只读属性),不要再持久化层实现,以避免上述问题。

除此之外,MeteorSeed 还从“是否允许 NULL”、属性切割、规范化(范式)、选择数据类型、优化并行等几个方面谈了设计原则。有关详细内容,可以查看 MeteorSeed 的博客原文

2013-04-04 09:3715788
用户头像

发布了 501 篇内容, 共 232.4 次阅读, 收获喜欢 54 次。

关注

评论

发布
暂无评论
发现更多内容

强化区块链技术在数字政府、智慧城市、智能制造等领域应用

CECBC

人工智能

图算法系列之深度优先搜索(二)

Silently9527

深度优先搜索 数据结构和算法 图算法

云上细粒度访问管理的参考架构

张晓辉

云原生 网关 访问控制 OPA

答对这八个Redis的问题,说明你精通了

AI乔治

Java redis 架构 分布式 高并发

对于医疗健康行业,区块链最大的价值在哪里?

CECBC

医疗

为什么区块链技术仍然被人们认为当成一个投机的工具?

CECBC

容器&服务:metrics-server探索

程序员架构进阶

k8s 28天写作 弹性扩容 4月日更 metrics server

浪潮×积成电子:尝到了工业互联网的“甜头”

浪潮云

云计算

美的蒸烤料理炉全新上线华为商城,首款搭载鸿蒙系统的设备有何不同?

科技汇

MySQL主从不一致情形与解决方法

AI乔治

Java MySQL 架构 主从同步

收藏!阿里P9耗时28天,总结历年亿级活动高并发系统设计手册

Java架构师迁哥

京东首席架构师深邃洞察:服务化+云原生+微服务

Java架构师迁哥

重装变态的微信

箭上有毒

生活记录 4月日更

深入浅出解读SpringMVC 进阶版

AI乔治

Java spring 架构 微服务 springmvc

工行首次全面展示数十项数字人民币研发试点成果

CECBC

数字人民币

面试别慌!阿里专家带你从【入门+基础+进阶+项目】攻破SpringBoot

Java架构师迁哥

别让心里的墙,挡住了你未来的路

小天同学

思考 认知提升 认知 4月日更

LeetCode题解:151. 翻转字符串里的单词,数组,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

全面复盘B站面试时坑我最深的Java并发:JDK源码剖析

Java架构师迁哥

一枚比特币变换一台车,特斯拉与比特币还要绑定多久?

CECBC

特斯拉

架构师必经之路!Github榜首Java代码优化:77案例+28技巧开源分享

Java架构师迁哥

云图说|读请求太多怎么办?一键读写分离来帮忙

华为云开发者联盟

MySQL 读写分离 云数据库 云数据库MySQL

Dubbo学习笔记

六维

dubbo 4月日更

如何在 Spring/Spring Boot 中优雅地做参数校验?

JavaGuide

Java spring springboot

智能小车系列-树莓派初次使用环境配置

波叽波叽啵😮一口盐汽水喷死你

树莓派 wifi SSH 无显示器 树莓派首次配置

持续交付实战

云飞扬

MySQL高可用架构:mysql+keepalived实现

AI乔治

Java MySQL 架构 高可用架构 keepalive

前端工程化-webpack

chun1123

大前端 webpack

小技巧 | 帮助运营小姐姐批量修改文件名的几种方式

梁龙先森

Node 脚本 PowerShell

爆肝1W+字,通俗易懂的讲解下Java注解

AI乔治

Java 架构 面试 注解

开发人员如何有效地进行数据库设计_DevOps_崔康_InfoQ精选文章