mysql数据库设计 14

数据库设计三大范式

在设计关系数据库的时候,一般来说我们都是需要遵从不同的规范要求来设计出合理的关系型数据库,这些不同的规范要 求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
范式分为:3大范式,以及BC范式,第四范式还有第五范式 一共六大范式通常来说满足与三大范式就基本足够 ;
注意:项目的数据库设计并不一定要完全满足与三大范式,有些时候我们会适量的冗余让Query尽两减少Join
误区:不是范式越高越就越好 好 => 结构清晰
早期:希望数据可以足够的小数据量不是问题主要分问题
现在:希望查询速度越快越好,同时操作越简单越好

第一范式(1NF)

简单地说,第一范式要求关系中的属性必须是原子项,即不可再分的基本类型,集合、数组和 结构不能作为某一属性出现,严禁关系中出现“表中有表”的情况在任何一个关系数据库系统中,第一范式是关系模 式的一个最起码的要求。不满足第一范式的数据库模式不能称为关系数据库。

原始表中,其中”工程地址”列还可以细分为省份,城市等。在国外,更多的程序把”姓名”列也分成2列,即”姓”和“名”。

虽然第一范式要求各列要保存原子性,不能再分,但是这种要求和我们的需求是相关联的,如上表中我们对”工程地址”没有省份,城市这样方面的查询和应用需求,则不需拆分,”姓名”列也是同样如此。

原始表:

工程号工程名称工程地址员工编号员工名称薪资待遇职务
P001–– 港珠澳大桥–– 广东珠海–– E0001–– Jack ––6000/月 ––工人
P001港珠澳大桥广东珠海E0002Join7800/月工人
P001港珠澳大桥广东珠海E0003Apple8000/月高级技工
P002南海航天海南三亚E0001Jack5000/月工人

第二范式(2NF)

第二范式(2NF)是在第一范式(1NF)的基础建立起来的,既满足第二范式(2NF)就必须要 满足第一范式。第二范式(2NF)要求实体的属性完全依赖于主键字。

第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。

例如:原始表中描述了工程信息,员工信息等。这样就造成了大量数据的重复。按照第二范式,我们可以将原始表分为工程信息表与员工信息表

工程信息表:

工程编号工程名称工程地址
P001港珠澳大桥广东珠海
P002南海航天海南三亚

员工信息表:

员工编号员工姓名职务薪资水平
E0001Jack工人3000/月
E0002Join工人3000/月
E0003Apple高级技工6000/月

第三范式(3NF)

第三范式(3NF)是第二范式的子集,既满足第三范式就必须满足第二范式。意思是不存在非 关键字段对任意候选关键字段的传递函数依赖

例如:
现在我们来看看在第二范式的讲解中,我们将表1-1拆分成了两张表。这两个表是否符合第三范式呢。在员工信息表中包含:”员工编号”、”员工名称”、”职务”、”薪资水平”,而我们知道,薪资水平是有职务决定,这里”薪资水平”通过”职务”与员工相关,则不符合第三范式。我们需要将员工信息表进一步拆分,如下:

员工信息表:

员工编号员工姓名职务编号
E0001Jack1
E0002Join1
E0003Apple2

工程信息表:

工程编号工程名称工程地址
P001港珠澳大桥广东珠海
P002南海航天海南三亚

职务表(Duty)

职务编号职务名称工资待遇
1工人3000/月
2高级技工6000/月

工程参与人员记录表:

编号工程编号人员编号
1P001E0001
2P001E0002
3P002E0003

通过对比我们发现,表多了,关系复杂了,查询数据变的麻烦了,编程中的难度也提高了,但是各个表中内容更清晰了, 重复的数据少了,更新和维护变的更容易了。

数据库表字段类型分析

字符串类型

charvarchar都是用来存储字符串类型的数据,但是他们保存和检索的方式不一样.
char属于固定长度的字符类型,
varchar属于可变长的字符类型

gbk,1个字符,两个字节

char(4)字节varchar(4)字节
"‘’8个字节"1个字节
‘ab’‘ab ’8个字节‘ab’5个字节
‘abcd’‘abcd’8个字节‘abcd’9个字节
‘abcdefg’‘abcd’8个字节‘abcd’9个字节

utf8(1个字符,两个字节

char(4)字节varchar(4)字节
"‘’12个字节"1个字节
‘ab’‘ab’12个字节‘ab’7个字节
‘abcd’‘abcd’12个字节‘abcd’13个字节
‘abcdefg’‘abcd’12个字节‘abcd’13个字节

由于char是固定长度的,所以它的处理速度比varchar快得多,但是其缺点是浪费存储空间,程序需要对尾行空格进行处理,所以对那些变化不打并且查询速度有较高的 要求的数据可以考虑使用char类型来存储

在mysql中,不同的存储引擎对char和varchar的使用原则有所不同

MyISAM存储引擎
建议使用固定长度的数列代替可变长度的数据列

InnoDB存储引擎
建议使用varchar类型,对于InnnoDB数据表,内部的行存储格式没有区分固定长度和可变长度,因此使用char列不一定比 可变长度的varchar性能好
由于char平均占用空间多余varchar,因此varchar来UI消化需要处理的数据航的存储总量和磁盘I/O是比较好的.

数字类型

数字类型解释 https://blog.csdn.net/zgmu/article/details/52118165

数据类型范围字节
bigint-2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,372,036,854,775,807)8 字节
| 0到18446744073709551615较大整数
int-2^31 (-2,147,483,648) 到 2^31-1 (2,147,483,647)4 个字节
| 0到4294967295标准整数
smallint-2^15 (-32,768) 到 2^15-1 (32,767)2 字节
| 0到65535较小整数
tinyint-2^7 (-128) 到 2^7 - 1 (123)1 字节
| 0到255非常小的整数
float[(m,d)]±1.175494351e - 384字节
double[(m, d)]±2.2250738585072014e - 3088字节
decimal (m,d)可变;其值的范围依赖于m 和dm+2字节

id 必为主键,类型为int bigint unsigned、单表时自增、步长为 1; 注意一下因为一些表可能因为数据量的关系导致主键会很大可能会超出int的范围这个时候就比较建议使用bigint通常int即可

注:不过当一个表数据量超过了500万的时候或者单表容量超过2GB的时候推介分库分表;这一步操作是需要实先对于数据量在项目上线之后的思考点

UNSIGNED属性就是将数字类型无符号化, unsigned的使用

注意 unsigned tinyint 的范围就是 0-255

CREATE TABLE `yyy` (
`id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`) )
ENGINE=InnoDB DEFAULT CHARSET=utf8
mysql> desc yyy;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| id    | tinyint(3) unsigned | NO   | PRI | NULL    |       |
+-------+---------------------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into yyy values(255);
Query OK, 1 row affected (0.06 sec)
mysql> select * from yyy;
+-----+
| id  |
+-----+
| 255 |
+-----+
1 row in set (0.00 sec)
mysql> insert into yyy values(256);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql> insert into yyy values(-1);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
mysql> insert into yyy values(0);
Query OK, 1 row affected (0.09 sec)

人的年龄用 unsigned tinyint( 表示范围 0-255,人的寿命不会超过 255 岁 )

status,sexuality 相对来说在系统中我们更愿意使用数字作为表示,代替实际该字段所传单的意思,因为char所占用 的3个字节,相对来说比较适合于unsigned tinyint

时间类型

注意: 默认情况下,当MySQL遇到超出范围的日期或时间类型的值或该类型的其他无效值时,它会将该值转换为“零”值的值。唯 一的例外是超出了范围。TIME值被裁剪 到TIME范围。

MySQL允许在DATE或DATETIME列。这对于需要存储您可能不知道确切日期的生日的应用程序非常有用。在这种情况下, 您只需将日期存储为’2009-00- 00’或’2009-01-00’。如果存储这样的日期,就不应该期望得到正确的结果,例 如DATE_SUB()或DATE_ADD()需要完整的日期。若要在日期中不允许零个月或日部分,请启用NO_ZERO_IN_DATE模式 。

MySQL允许您存储“零”价值’0000-00-00’作为“假约会。”在某些情况下,这比使用NULL值,并使用较少的数据和索引空 间。不允许’0000-00-00’,启用NO_ZERO_DATE模式。

DATETIME

DATETIME 用于表示 年月日 时分秒,是 DATE 和 TIME 的组合,并且记录的年份(见上表)比较长久。如果实际应用 中有这样的需求,就可以使用 DATETIME 类型。
1、 DATETIME列可以设置为多个,默认可为null,可以手动设置其值。
2、 DATETIME列不可设定默认值。
3、 DATETIME列可以变相的设定默认值,比如通过触发器、或者在插入数据时候,将DATETIME字段值设置为now(),这样可以做到了,尤其是后者,在程序开 发中常常用到。

TIMESTAMP

TIMESTAMP 用于表示 年月日 时分秒,但是记录的年份(见上表)比较短暂,TIMESTAMP列必须有默认值,默认值可以 为“0000-00-00 00:00:00”,但不能为null
TIMESTAMP 和时区相关,更能反映当前时间。当插入日期时,会先转换为 本地时区后再存放;当查询日期时,会将日期转换为 本地时区后再显示。所以不同时区的人看到的同一时间是 不一样的 。表中的第一个 TIMESTAMP 列自动设置为系统时间(CURRENT_TIMESTAMP)。当插入 或更新一行,但没有明确给TIMESTAMP 列赋值,也会自动设置为当前系统时间。如果表中有第二个 TIMESTAMP 列,则默认值设置为0000-00-00 00:00:00。TIMESTAMP 的属性受 Mysql 版本和服务器 SQLMode 的影响较大。如果记录的日期需要让不同时区的人使用,最好使用 TIMESTAMP。

注:一般建表时候,创建时间用datetime,更新时间用timestamp。

DATE

DATE 用于表示 年月日,如果实际应用值需要保存 年月日 就可以使用 DATE。

TIME

TIME 用于表示 时分秒,如果实际应用值需要保存 时分秒 就可以使用 TIME。

YEAR

YEAR 用于表示 年份,YEAR 有 2 位(最好使用4位)和 4 位格式的年。 默认是4位。如果实际应用只保存年份,那么用 1 bytes 保存 YEAR 类 型完全可以。不但能够节约存储空间,还能提高表的操作效率。

不推荐存储的数据类型

二进制多媒体数据 将二进制多媒体数据存放在数据库中,一个问题是数据库空间资源耗用非常严重,另一个问题是 这些数据的存储很消耗数据库主机的CPU 资源。这种数据主要 包括图片,音频、视频和其他一些相关的二进制文件。 这些数据的处理本不是数据的优势,如果我们硬要将他们塞入数据库,肯定会造成数据库的处理资源消耗 严重。

流水队列数据 我们都知道,数据库为了保证事务的安全性(支持事务的存储引擎)以及可恢复性,都是需要记录所 有变更的日志信息的。而流水队列数据的用途就决定了存放 这种数据的表中的数据会不断的被 INSERT,UPDATE 和 DELETE,而每一个操作都会生成与之对应的日志信息。在 MySQL 中,如果是支持事务的存储引擎,这 个日志的产生量 更是要翻倍。而如果我们通过一些成熟的第三方队列软件来实现这个 Queue 数据的处理功能,性能将会成倍的提升。

超大文本数据 对于 5.0.3 之前的 MySQL 版本,VARCHAR 类型的数据最长只能存放 255 个字节,如果需要存储 更长的文本数据到一个字段,我们就必须使用 TEXT 类型(最大 可存放 64KB)的字段,甚至是更大的LONGTEXT 类型 (最大 4GB)。而 TEXT 类型数据的处理性能要远比 VARCHAR 类型数据的处理性能低下很多。从 5.0.3 版 本开始 ,VARCHAR 类型的最大长度被调整到 64KB 了,但是当实际数据小于 255Bytes 的时候,实际存储空间和实际的数据长 度一样,可一旦长度超过 255 Bytes 之后,所占用的存储空间就是实际数据长度的两倍。 对于图片的存储,如果说是 特殊情况可以使用BLOB,但是通常来说跟推介使用varchar存图片路径,而图片会放在一个文件夹中

下一篇:mysql主从复制与备份 15
上一篇:mysql 问题处理 13

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值