MySQL是目前最流行的关系型数据库之一,在阿里巴巴若干几年的去IOE化后整风运动后,
MySQL从中小型数据库解决方案一路成长为了大型互联网应用关系型数据库解决方案的中流砥柱。
MySQL是一个关系型数据库管理系统,先被SUN公司收购,后又被Oracle收购。
因为MySQL免费且开源,还可以无限扩展成N个数据库集群,玩读写分离+分库分表。
虽然NOSQL、NEWSQL等技术犹如雨后春笋般发展壮大,
但关系型数据库依然还是各大互联网企业核心业务数据的基石,目前依然占据大量的市场,
其霸主地位未来短时间内也难以撼动,并且mysql的生态体系已经发展的相当完善,
网上的资料也非常多,绝对是关系型数据库解决方案的领跑者。
关系型数据库与NOSQL、NEWSQL并不是竞争关系,而是相互配合的关系,
NOSQL、NEWSQL等因为没有完善的生态链和一些尖锐问题并没办法真正颠覆关系型数据库。
MYSQL可以与很多技术结合使用,彰显巨大威力,例如:
memcached、redis、mycat、druid、mongodb、sharding-jdbc等等等等。
数据库就是用来存储和读取数据的地方。我们可以对数据进行增删改查等操作,
当然,数据也可以不存储在数据库中,那么可以存储在什么地方?
例如可以存储在内存中,DVD中,excel中,硬盘的某个文件中等等。
那为什么非得要存储在数据库中呢?因为专人专事,
用最专业的软件干最专业的事情。
我们的程序需要对数据库中的数据进行增删改查等业务操作,
很多业务逻辑都是建立在数据库的基础之上衍生而来,
是互联网应用中必不可少的组件。
所谓关系型数据库是建立在关系模型基础上的数据库,
例如一对一关系,一对多,多对多等等。
概 念 | 别 名 | 描述 |
---|---|---|
实例 |
instance | 部署在某个节点上的mysql服务,一个实例上可以建多个库。 |
库 |
database | 最大的逻辑存储单元,库是一些表的集合。 |
表 |
table | 表是数据的矩阵,表有点像一个电子表格,表是存储数据的逻辑单元,以行和列的形式存在;列就是字段,行就是记录。 |
列 |
column | 一列包含了相同的数据, 例如邮政编码的数据。 |
行 |
row | 一行是一组相关的数据,例如一条用户订阅的数据。 |
主键 |
primary key | 主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。 |
外键 | foreign key | 外键用于关联两个表,很多厂禁止使用物理外键。 |
索引 |
index | 使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,类似于书籍的目录。 |
数据字典 | schema | 系统表,存放数据库相关信息的表,系统表里的数据通常由数据库系统维护,程序员不应该手动修改系统表以及内部数据,程序员可以查看系统表的数据。 |
约束 | constraint | 执行数据校验的规则,用于保证数据的完整性的规则。 |
视图 | view | 一个或多个数据表里数据的逻辑显示,视图并不存储数据。 |
索引 | index | 用于提高查询性能,相当于书的目录。 |
函数 | function | 用于完成一次特定的计算,具有一个返回值。 |
存储过程 | procedure | 用于完成一次完整的业务处理,没有返回值,但可以通过传出参数将多个值传给调用环境。 |
触发器 | trigger | 相当于一个事件监听器,当数据库发生特定事件后,触发器被触发,完成相应的处理。 |
存储引擎 | 未完待续。 |
注意:大中型互联网项目中禁止使用触发器、存储过程、视图等数据对象以提升数据库性能。
表与表之间的关系
在mysql中,表与表之间是有关系的,就好像人与人之间也有关系一样,
人与人的关系可以是同学,朋友,亲人,恋人,陌生人等等。
表与表之间的关系分为:一对一,一对多,多对多,多对多,
所谓的关系型数据库,关系~
A表的一条数据对应B表的一条数据。
一对一又分为:双向主键一对一,特殊一对多等情况。
A表的一条数据对应B表的多条数据。
(记住一个关于entity bean的口诀,一方有多方的集合,多方有一方的ID。)
在B表中应该有一个字段存储A表记录的id。
A表的多条数据对应B表的一条数据。
在A表中应该有一个字段存储B表记录的id。
A表的一条数据对应B表的多条数据,B表的一条数据对应A表的多条数据。
多对多关系比较要创建一张中间表,中间表中要有两张表的主键作为联合主键。
建表时需要指定每列的数据类型,对于不同用途的列,
创建合适的数据类型也是一项重要的MySQL优化方案,
一般情况下,我们不会往数据库存大对象数据、枚举、集合。
tinyint
/smallint/mediumint/int
/bigint类型 | 大小(字节) | 范围(有符号) | 范围(无符号) |
---|---|---|---|
tinyint |
1 | (-128,127) | (0,255) |
smallint | 2 | (-32768,32767) | (0,65535) |
mediumint | 3 | (-8388608,8388607) | (0,16777215) |
int |
4 | (-2147483648,2147483647) | (0,4294967295) |
bigint | 8 | (-9223372036854775808,9223372036854775807) | (0,18446 744073709551615) |
这些类型在很大程度上是相同的,只有它们存储的值的大小是不相同的,区别仅仅是表数范围不同。
MySQL会在不合规定的值插入表前自动修改为0。
UNSIGNED修饰符规定字段只保存正值。因为不需要保存数字的正、负符号,
可以在储时节约一个“位”的空间。从而增大这个字段可以存储的值的范围。
ZEROFILL 修饰符规定 0(不是空格)可以用来补全输出的值。
注意:数值类型中length不会影响字段的大小和它可以存储的值的范围。
自己做的实验:
将一个表的a字段改成tinyint signed,length修改成100,结果也只是能输入到127这个数字,
永远没办法大于127,这就说明这个Length并不是字段的长度,至少在整型里是这样)。
万一我们需要对一个字段存储一个超出许可范围的数字,
MySQL 会根据允许范围最接近它的一端截断后再进行存储。
4/8字节小数,单/双精度浮点类型,与整数一样,
这些类型也带有附加参数:一个显示宽度指示器和一个小数点指示器。
比如float(7,3) 规定显示的值不会超过7位数字,小数点后面带有3位数字。
对于小数点后面的位数超过允许范围的值,MySQL会自动将它四舍五入为最接近它的值,再插入它。
精确小数类型,相对于float和double不会产生精度丢失的问题,
decimal用于精度要求非常高的计算中,
这种类型允许指定数值的精度和计数方法作为选择参数。
精度在这里指为这个值保存的有效数字的总个数,而计数方法表示小数点后数字的位数。
比如decimal(7,3) 规定了存储的值不会超过7位数字,并且小数点后不超过3位。
char/varchar
0-255/0-65535字节定长/变长字符串类型,
char比指定长度大的值将被截断,而比指定长度小的值将会用空格作填补。
char类型的一个变体是varchar类型。
它是一种可变长度的字符串类型,
短于长度的varchar不会被空格填补,但长于长度的值仍然会被截短。
varchar可以根据实际内容动态改变存储值的长度,
所以在不能确定字段需要多少字符时使用varchar类型可以大大地节约磁盘空间、提高存储效率。
定长/变长二进制字符串类型,以二进制形式保存字符串
0-255/0-65535/0-16777215/0-4294967295字节的文本对象,
可用于存储超长长度的字符串,分别可存储255B/64KB/16MB/4GB大小的文本。
0-255/0-65535/0-16777215/0-4294967295字节的二进制大对象,
可用于存储图片,音乐等二进制数据,分别可存储255B/64KB/16MB/4GB大小的数据,
但通常不把文件存储在数据库中,而是存储在文件服务器,在数据库中存储文件的地址即可。
对于字段长度要求超过255个字节的情况下,MySQL提供了TEXT和BLOB两种类型。
BLOB类型区分大小写,而TEXT不区分大小写。
比指定类型支持的最大范围大的值将被自动截短。
类型 | 大小(字节) | 范围 | 说明 |
---|---|---|---|
date | 4 | 1000-01-01/9999-12-31 | 日期类型,YYYY-MM-DD,不能保存时间 |
time | 3 | ‘-838:59:59’/‘838:59:59’ | 时间类型,HH:MM:SS,不能保存日期 |
year | 1 | 1901/2155 | 年类型,YYYY,仅仅保存年份 |
datetime |
8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | 日期时间类型,YYYY-MM-DD HH:MM:SS |
timestamp | 4 | 1970-01-01 00:00:00/2037 | 时间戳类型,YYYYMMDD HHMMSS。 |
这些类型可以描述为字符串或不带分隔符的整数序列。
如果描述为字符串,DATE类型的值应该使用连字号作为分隔符分开,
而TIME类型的值应该使用冒号作为分隔符分开。
需要注意的是,没有冒号分隔符的TIME类型值,
将会被MySQL理解为持续的时间,而不是时间戳。
datetime/timestamp
datetime和timestamp是两种混合类型,它们可以把日期和时间作为单个的值进行存储。
如果将timestamp类型字段设置默认值为CURRENT_TIMESTAMP,
则数据新增和修改的时候,timestamp类型字段会自动更新成MySql系统时间
int
1.占用4个字节
2.建立索引之后,查询速度快
3.条件范围搜索可以使用使用between
4.不能使用mysql提供的时间函数
结论:适合需要进行大量时间范围查询的数据表
datetime
1.占用8个字节
2.允许为空值,可以自定义值,系统不会自动修改其值。
3.实际格式储存(Just stores what you have stored and retrieves the same thing which you have stored.)
4.与时区无关(It has nothing to deal with the TIMEZONE and Conversion.)
5.可以在指定datetime字段的值的时候使用now()变量来自动插入系统的当前时间。
结论:datetime类型适合用来记录数据的原始的创建时间,因为无论你怎么更改记录中其他字段的值,datetime字段的值都不会改变,除非你手动更改它。
timestamp
1.占用4个字节
2.允许为空值,但是不可以自定义值,所以为空值时没有任何意义。
3.TIMESTAMP值不能早于1970或晚于2037。这说明一个日期,例如’1968-01-01’,
虽然对于DATETIME或DATE值是有效的,但对于TIMESTAMP值却无效,如果分配给这样一个对象将被转换为0。
4.值以UTC格式保存( it stores the number of milliseconds)
5.时区转化 ,存储时对当前的时区进行转换,检索时再转换回当前的时区。
6.默认值为CURRENT_TIMESTAMP(),其实也就是当前的系统时间。
7.数据库会自动修改其值,所以在插入记录时不需要指定timestamp字段的名称和timestamp字段的值,
你只需要在设计表的时候添加一个timestamp字段即可,插入后该字段的值会自动变为当前系统时间。
8.以后任何时间修改表中的记录时,对应记录的timestamp值会自动被更新为当前的系统时间。
结论:timestamp类型适合用来记录数据的最后修改时间,因为只要你更改了记录中其他字段的值,timestamp字段的值都会被自动更新。
enum(‘a’,‘b’),枚举类型,该列的值只能是enum后括号内多个值的其中之一。
set(‘a’,‘b’),集合类型,该列的值可以是set后括号内多个值得其中几个。
该类型比较少用,详情请搜索"mysql enum is evil"。
因此不再赘述。
约束是在表上强制执行的数据校验规则,约束主要用于保证数据库里数据的完整性。
除此之外,当表中的数据存在相互依赖性时,可以保护相关的数据不被删除。
约束也是数据库对象,并被存储在系统表中,拥有自己的名字,约束分单列约束和多列约束。
约束可以在建表时以及建表后通过ALTER命令创建。
mysql使用information_schema库里的TABLE_CONSTRAINTS来保存约束信息。
NOT NULL约束
非空约束,指定某列不能为空。
注意事项:
CREATE TABLE t_user(
user_id INT AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT '用户ID主键',
user_name VARCHAR(20) DEFAULT '' COMMENT '用户名称'
) COMMENT='用户表';
ALTER TABLE t_user MODIFY user_name VARCHAR(20) NOT NULL;
#取消非空约束
ALTER TABLE t_user MODIFY user_name VARCHAR(20) NULL;
UNIQUE约束
唯一约束,指定某列或者几列组合不能重复,但允许出现多个NULL值。
创建唯一约束后,mysql会自动为其创建唯一索引,默认约束名等于列名。
CREATE TABLE t_user(
user_id INT AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT '用户ID主键',
user_name VARCHAR(20) UNIQUE DEFAULT '' COMMENT '用户名称'
) COMMENT='用户表';
#两列的组合不能有重复
CREATE TABLE t_user_info(
user_id INT AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT '用户ID主键',
user_name VARCHAR(20) DEFAULT '' COMMENT '用户名称',
user_age INT(2) COMMENT '用户年龄',
CONSTRAINT test_unique UNIQUE(user_name,user_age)
) COMMENT='用户表';
ALTER TABLE t_user_info ADD UNIQUE(user_name,user_age);
ALTER TABLE t_user_info MODIFY user_age INT(2) UNIQUE;
#删除约束
ALTER TABLE t_user_info DROP INDEX user_age;
PRIMARY KEY约束
主键,指定该列的值可以唯一的标识该条记录,相当于非空约束+唯一约束。
mysql会自动为其创建唯一索引,允许为多列建立组合主键约束。
一张表最多只能有一个主键,主键是表中能够唯一确定一行记录的字段或字段组合。
一旦设置了AUTO_INCREMENT则表示整型字段自增,由数据库自动维护该字段。
CREATE TABLE t_user(
user_id INT AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT '用户ID主键',
user_name VARCHAR(20) UNIQUE DEFAULT '' COMMENT '用户名称'
) COMMENT='用户表';
#多列组合索引
CREATE TABLE t_user(
user_id INT NOT NULL COMMENT '用户ID主键',
user_name VARCHAR(20) UNIQUE DEFAULT '' COMMENT '用户名称',
PRIMARY KEY(user_id,user_name)
) COMMENT='用户表';
#删除主键
ALTER TABLE t_user DROP PRIMARY KEY;
ALTER TABLE t_user ADD PRIMARY KEY(user_id,user_name);
外键,指定该行记录从属于主表中的一条记录,主要用于保证参照完整性。
从表外键参照的只能是主表主键列或者唯一键列,同一个表内可以有多个外键,
建立外键约束时,mysql会为该列创建索引。外键多用于一对一,一对多,多对多关系。
当主表记录被从表记录参照时,主表记录不允许删除,必须要先删除对应的从表数据。
也可以设置级联删除:
on delete cascade (级联删除)
on delete set null (级联设置为null)
由于各大互联网公司全部禁用物理外键,使用逻辑外键,因此不再展开。
视图看上去非常像一个数据表,但它不是数据表,因为它并不能存储数据。
视图只是一个或多个数据表中数据的逻辑显示。视图的本质就是一条被命名的sql查询语句。
一旦视图被建立后就跟查询普通数据表没什么区别了。
视图的优点如下:
1、可以限制对数据的访问。
2、可以使复杂的查询变得简单。
3、提供了数据的独立性。
4、提供了对相同数据的不同显示。
由于各大互联网公司全部禁用视图,因此不再展开。
每个数据库实例都会具有一个数据库字典information_schema
(又称系统表、元数据表metadata),
用于存储数据对象信息以及其他系统级的信息。
当数据库表创建成功后,mysql使用information_schema数据库里的
tables表来保存该数据库实例中的所有数据表,
用户可以通过查询TABLES表来获取该数据库的表信息。
表:tables
数据库信息:schemata
视图:views
列信息:columns
触发器信息:triggers
存储过程+函数:routines
约束:tables_constraints
所有约束的键信息:key_column_usage
索引:statistics
今天我们学习了一些MySQL的基础知识,让大家有一个感性的认识,
其中库、表、行、列这四个概念最为核心,是必须要掌握的知识点。
并且许多场景下,做业务系统时,都需要先对数据库建模,
因此学好MySQL成为了一项必须通关的游戏。