Python高效开发实战:Django、Tornado、Flask、Twisted(第3版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.1 数据库的概念

尽管数据库本身可以指任何以存储数据为目的的软硬件系统,但由于关系数据库在当今Web开发中的重要地位,本书中的数据库只指用E-R图建模、使用SQL或ORM进行交互的关系数据库。

4.1.1 Web开发中的数据库

任何应用系统都离不开对数据的增加、删除和修改,Web系统也不例外。读者可以回忆一下自己常用的网站,除了有精美的网页、人性化的交互,所有站点的核心功能都是围绕着数据展开的。

• 购物网站上,琳琅满目的商品、价格、购物记录、支付状态都通过数据库进行保存。

• 社交网站上,博客消息、好友状态、朋友关联都由数据库提供支撑。

• 技术论坛上,话题板块分类、文章帖子、网友跟帖都要由数据库管理。

• 搜索引擎中,各种关键字、网页快照都由数据库进行索引和保存。

网站系统的设计一般遵循三层架构,即将网站系统在逻辑上分为三层:客户端层(HTML、CSS、JavaScript)、业务逻辑层(Python)、数据访问层(Python)。其中客户端层直接服务于用户,业务逻辑层为客户端层服务,数据访问层为业务逻辑层提供数据支持,数据访问层直接和数据库打交道。Web系统的三层架构如图4.1所示。

图4.1 Web系统的三层架构

从图4.1可以看出数据库为整个网站提供基础服务,图4.1同时给出了和数据库相关的3种人员的角色,对他们各自的行为总结如下。

• 用户:通过客户端软件(Web浏览器)访问网站,通过业务逻辑层和数据访问层间接获得数据服务。

• 开发者:设计和开发三层架构中的所有程序,与数据库相关的部分包括数据库模型建立、数据访问代码开发等。

• 数据库管理员:通过数据库管理系统(DBMS)对数据库进行维护和配置,包括数据库性能分析、性能改进、数据备份、数据恢复等。

由此可见,作为网站开发者的读者,需要具备数据库建模(E-R图)和开发数据访问代码(SQL或ORM)的能力。

在Web架构设计期,我们通常需要考虑数据库选型。数据库选型的依据一般为开发人员的熟练程度、费用、数据规模、性能要求、集群能力等,也可参考数据库管理员的建议。对当前比较常见的数据库介绍如下。

• PostgreSQL:始于1986年的著名开源数据库,在灵活的BSD风格许可证下发行。PostgreSQL的特性覆盖了SQL-2/SQL-92和SQL-3/SQL-99,几乎包括了世界上最丰富的数据类型,“IP类型”等数据类型连商业数据库都不具备。但它在数据集群及管理工具上不如一些商业数据库。

• MySQL:瑞典MySQL AB公司开发的开源数据库,目前为Oracle旗下的公司,是一种快速、多线程、多用户的SQL数据库服务器,在Web开发领域比较常见,可以轻易地支持上千万条数据的数据量。其缺点是由于缺乏官方资料而比较难学,开发者在开发中遇到问题时需要自己钻研,对存储过程的支持也比较有限。

• Oracle:很长时间以来最著名、市场占有率最高的商业数据库。Oracle以极强的数据一致性能力而著称,因而常见于金融、通信、政府等大型项目中。对几乎所有操作系统都有良好的支持。其缺点是价格昂贵,一般小项目较少选择Oracle。

• MS SQL Server:微软发布的商业数据库,其图形化的用户界面使系统管理和数据库管理更加直观、简单,而且与Windows完全集成,可以利用Windows的许多功能,如管理登录安全性、Office报表展现等。它在Windows平台下是极其优秀的关系数据库,缺点是尚无Linux平台版本。

• SQLite:一个轻量级、跨平台的关系数据库,支持SQL 92中的大部分功能。与以上数据库不同的是,SQLite不是C/S模式的数据库,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。由于其轻量级的特点,SQLite常用于嵌入式设备或并发可能性很低的场合。

4.1.2 关系数据库建模

数据库建模(Database Modeling)是指针对一个给定的应用环境构造数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足用户的应用需求。在现代敏捷开发方法的指导下,明确Web系统的业务需求后,关系数据库建模通常由以下两步完成。

• 设计E-R图:构造一个反映现实世界实体之间联系的模型。

• 关系表设计:将E-R图转换为关系表,并定义列类型,建立主键、外键等各种约束。

1. 设计E-R图

E-R图,即实体-关系(Entity-Relationship)图,是P.P.S.Chen于1976年提出的数据建模方法,由于其简单实用,得到了普遍应用,是目前描述信息结构最常用的方法。E-R图通过以下3种概念描述信息结构。

• 实体:客观存在的事物、事件、角色等,比采购员、老师、课程、订单等。

• 实体属性:用于描述实体的特性,每个实体可以有多个属性,如老师的性别、名字、住址等。

• 关系:反映两个实体之间客观存在的关系。

设计E-R图就是围绕着识别系统中的实体和明确实体之间关系而进行的。E-R图中两个实体(假设分别为实体A和实体B)的关系被分为以下3类。

• 一对一关系:实体A的任意一个实例至多只有一个实体B的实例与之关联;而实体B的任意一个实例也至多只有一个实体A的实例与之关联。典型的一对一关系包括人与身份证、丈夫与妻子等。一对一关系在E-R图中被记为1∶1。

• 一对多关系:实体A的任意实例可以有零个、一个或多个实体B的实例与之关联;而实体B的任意实例至多只与一个实体A的实例关联。典型的一对多关系包括班级与学生、人与银行卡等。一对多关系在E-R图中被记为1∶N

• 多对多关系:实体A的任意一个实例可以与实体B中的任意多个实例关联;而实体B中的任意一个实例也可以与实体A中的任意多个实例关联。典型的多对多关系包括老师和班级、学生与课程等。多对多关系在E-R图中被记为MN

在E-R图的绘制中,通常用方块表示实体,用实体周围的圆圈表示属性,用实体之间的菱形表示关系。图4.2是一个学校系统的E-R图示例。

图4.2 学校系统的E-R图示例

图4.2中定义了4个实体和3个关系,实体分别是“老师”“课程”“学生”“学生证”。实体的各个属性如图4.2中的圆圈部分所示。3个关系分别是:课程与老师之间的一对多任教关系(假设学校只允许一个老师教一门课程,但一门课程可以有多个老师任教);课程与学生之间的多对多选课关系(每门课程可以有多个学生学习,每个学生可以选择多门课程);学生与学生证的一对一入学关系(每个学生在入学时办理唯一的学生证)。

2. 关系表设计

在完成了数据需求分析和E-R图设计后,就可以进行关系表的具体设计了。将E-R图设计转变为关系表设计可按照如下步骤进行。

• 数据库选型,如MySQL、SQL Server、Oracle、PostgreSQL等。因为各种数据库支持的列类型略有不同,所以需要在物理表设计之前完成选型。

• 将每个实体转换为一个数据表,将实体的属性转换为该表中的列,为每个列定义相应的数据类型。

• 对于1∶1关系的两个表,为两个表设置相同的主键列。

• 对于1∶N关系的两个表,在N表中添加一个外键列,该列与1表的主键相关联。

• 对于MN关系,生成一个单独的表表示该关系,该关系的列由两个表的主键组成。

• 重新审核所有的表,在需要的地方添加约束,对常用的条件字段设置索引。

通过上述步骤,可以将图4.2中的实体关系模型转换为具体的关系表。该图一共生成了5个表:4个实体表和1个关系表。假设数据库采用PostgreSQL,则转换后的表定义如表4.1、表4.2、表4.3、表4.4和表4.5所示。

表4.1 表定义——课程

表4.2 表定义——老师

表4.3 表定义——学生

表4.4 表定义——学生证

表4.5 表定义——选课

在以上表定义中,读者尤其应该注意关系的表达方法。

• 表student和表card通过设置相同的主键(即student_id)实现了1∶1关系。

• 表teacher中通过设置外键course_id实现了与课程的1∶N关系。

• 表enroll实现了“学生”与“课程”的MN关系。

考虑到可能会有不熟悉数据库理论的读者,这里将表4.1~表4.5中的键型、索引、约束解释如下。

• Index:索引,是对数据库表中一列或多列的值进行排序的一种结构。对常用的查询条件字段添加索引可显著提高SQL语句的性能。

• Constraint:约束,是对列数据取值的某种限定。常见的约束有主键、外键、非空、唯一等。

• PK:主键(Primary Key),唯一标识一条记录,不允许为空。在大多数数据库中主键列也是一个索引列。

• FK:外键(Foreign Key),是另一个表的主键,表示关联关系,可以是空字段。

• NOT NULL:非空约束,即不允许列值为空。