9.1 为什么需要设计
当数据库比较复杂的时候,需要设计
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据插入和删除都麻烦,而且可能会有异常
- 程序的性能差
良好的数据库设计:
- 结节约内存空间
- 保证数据库的完整性
- 方便我们开发系统
软件开发中,关于数据库的设计
- 分析业务和需要处理的数据的需求
- 概要设计,设计关系图 E-R图
设计数据库的步骤:(例如个人博客)
收集信息,分析需求
- 用户表(用户登录注销,用户的个人信息,写博客,创建分类)
- 分类表(文章分类,谁创建的)
- 文章表(文章信息)
- 评论表
- 友链表(友情链接)
- 自定义表(系统信息,某个关键的字,或者一些主字段) key : value)
- 说说表:发表心情,创建时间
- 粉丝表
像下面这些数据,是统计出来的,不用单独建表存放
标识实体(把需求落地)
用户表
分类表
文章表
评论表
友链表
粉丝表
/*
SQLyog Professional v12.08 (32 bit)
MySQL - 5.5.40 : Database - blog
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`blog` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `blog`;
/*Table structure for table `blog_article` */
DROP TABLE IF EXISTS `blog_article`;
CREATE TABLE `blog_article` (
`id` int(10) NOT NULL COMMENT '文章的唯一标识',
`title` varchar(100) NOT NULL COMMENT '文章标题',
`author_id` int(10) NOT NULL COMMENT '编写文章的用户',
`category_id` int(10) NOT NULL COMMENT '文章分类',
`content` text NOT NULL COMMENT '文章内容',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '修改时间',
`love` int(10) NOT NULL COMMENT '点赞',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `blog_article` */
/*Table structure for table `category` */
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` int(10) NOT NULL,
`category_name` varchar(30) NOT NULL,
`category_user_id` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `category` */
/*Table structure for table `comment` */
DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
`id` int(10) NOT NULL COMMENT '评论id',
`blog_id` int(10) NOT NULL COMMENT '在哪一个文章下面评论的',
`user_id` int(10) NOT NULL COMMENT '评论的人',
`comment` varchar(2000) NOT NULL COMMENT '评论的内容',
`create_time` datetime NOT NULL COMMENT '评论创建的时间',
`user_id_parent` int(10) NOT NULL COMMENT '回复的人的id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `comment` */
/*Table structure for table `links` */
DROP TABLE IF EXISTS `links`;
CREATE TABLE `links` (
`id` int(10) NOT NULL COMMENT '友链id',
`links` varchar(50) NOT NULL COMMENT '网站名称',
`href` varchar(2000) NOT NULL COMMENT '网站链接',
`sort` int(10) NOT NULL COMMENT '友链排序',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `links` */
/*Table structure for table `user` */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '用户的唯一ID',
`username` varchar(60) NOT NULL COMMENT '用户名',
`password` varchar(60) NOT NULL COMMENT '用户密码',
`sex` varchar(2) NOT NULL,
`age` int(3) NOT NULL,
`sign` varchar(200) NOT NULL,
`open_id` varchar(1000) NOT NULL COMMENT '微信id',
`avator` varchar(1000) NOT NULL COMMENT '头像(图片地址)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `user` */
/*Table structure for table `user_follow` */
DROP TABLE IF EXISTS `user_follow`;
CREATE TABLE `user_follow` (
`id` int(10) NOT NULL COMMENT '唯一标识',
`user_id` int(10) NOT NULL COMMENT '被关注的id',
`follow_id` int(10) NOT NULL COMMENT '关注人的id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `user_follow` */
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
标识实体之间的关系
写博客:user写博客
创建分类:user创建分类(category)
关注:user跟user有关注与被关注的关系
友链:不需要与任何关联
评论:user-user-blog
9.2 三大范式
为什么需要数据规范化?
1:因为数据会重复
2:更新会有异常
3:插入异常(无法正常显示信息)
4:删除异常(丢失有效信息)
三张图搞透第一范式(1NF)、第二范式(2NF)和第三范式(3NF)的区别(强烈推荐)
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
通俗的理解是,字段还可以再分吗?如过不能,则是符合1NF的设计。
第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
简单的解释,比如你和一个女生约会建立一张表,不用每条约会记录都记录她的身高、体重,将身高体重单独的存在一张表中供查询即可。
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
打个比方,比如评论表,如果你将用户ID,用户头像都放在这留言表中,就是不合适的了。用户头像是依赖于用户ID,而不依赖该评论。
第一范式
要求数据库表中的每一列都是不可分割的原子数据项
第二范式
前提:满足第一范式,每张表只描述一件事情
第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关
咱们把订单号和产品号看成联合主键
简单的说第二范式要求确保数据库表中的每一列都与主键相关,而不能只与主键的某一部分相关(针对联合主键而言,有些表有多个主键),即一个表存只能储存一种数据.
第三范式
前提:满足第一范式和第二范式
任何非主属性不依赖于其他非主属性,即在第二范式(2NF)基础上消除传递依赖
第三范式需要去报数据库表中的每一列数据都和主键直接相关,而不能间接相关
满足3NF的前提是必须满足2NF。另外关系模式的非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列m既依赖于全部主键,又依赖于非主键列n的情况。不能存在下图的蓝色线的情况,只要非主键内部存在传递依赖,就不满足第三范式。
第三范式(Third Normal Form,3rd NF)就是指表中的所有数据元素不但要能惟一地被主关键字所标识,而且它们之间还必须相互独立,不存在其他的函数关系。也就是说,对于一个满足2nd NF 的数据结构来说,表中有可能存在某些数据元素依赖于其他非关键字数据元素的现象,必须消除。
简单的说第三范式要求确保数据表中的每一列数据都和主键直接相关,而不能间接相关,属性不能依赖于其他非主属性.
假设存在关系模式主键1: 课程编号; 列1: 教师名; 列2: 教师家庭地址。显然满足第一范式和第二范式,但是教师家庭地址传递依赖于教师名,所以不满足第三范式。
总结:
1NF:把每一列说清楚
2NF:把每一个表说清楚
3NF:消除依赖
第二范式要求非主键属性与所有主键相关(针对联合主键,单主键必然满足第二范式),第三范式则在第二范式的基础上要求所有非主键属性互相独立,即互不相关.
若每个非主属性与所有主键都相关,那么可以说这张表满足了第二范式.更进一步,依次取每一个非主属性查看其与其他非主属性的关系,若每个非主属性之间相互独立,那么可以说这张表满足了第三范式.
第二范式是完全函数依赖,第三范式是消除传递依赖
规范性和性能的问题
关联查询的表不得超过三张表
考虑商业化的需求和目标,(成本,用户体验!)数据库的性能更加重要·在规范性能的问题的时候,需要适当的考虑一下规范性!
故意给某些表增加一些冗余的字段。(从多表查询中变为单表查询)
故意增加一些计算列(从大数据量降低为小数据量的查询:索引)