本章节从MySQL的安装到基础使用,MySQL本身只是一个SQL接口,它内部还包含多种数据引擎,常用的包括:
- InnoDB:支持事务的数据库引擎(不知道选啥的时候选他就好)
- MyISAM:早期默认,不支持事务
接口和引擎的关系好比浏览器和浏览器引擎,切换MySQL引擎不影响自己写的应用程序使用MySQL的接口,由于其开源,也衍生出了各种开源版本(包括针对各种云存储中托管数据库的版本等)
安装MySQL
Windows直接官网下载对应的版本就好了,Community Version 在该超链接进行下载,其他版本就按需下载,按需付费就行。
Linux下载MySQL:
sudo apt-get install mysql-server
验证是否下载安装完成:
# 链接服务器
mysql
# 登录服务器(需要输入口令)
mysql -u root -p
成功链接后会变成mysql>
,输入exit
可以推出MySQL命令行,但是其将仍然在后台运行。
关系模型
关系数据建立在关系模型之上,关系模型本质上就是若干个存储数据的二维表(Excel表),其中
- 每一行称为记录(Record):记录是一个逻辑意义上的数据
- 每一列成为字段(Column):同一个表的每一行记录都拥有相同的若干字段,字段需要规定其数据类型,以及是否允许为Null(缺省值)
避免允许Null,不允许可简化查询条件,加快查询速度,也避免程序调用时需要处理Null
关系数据的表和表之间的跳转可以建立“一对多”,“多对一”和“一对一的关系”,这样才能按照应用册灰姑娘徐的逻辑来组织和存储数据,通俗的讲 :
- 一个班级可以对应很多学生
- 多位学生对应同个班级
- 一个班级对应一个班主任
在关系数据库中,关系是通过主键和外键来维护的。
主键
在关系数据库中,一张表中的每一行数据被称为一条记录。一条记录就是由多个字段组成的。例如,students
表的两行记录:
id | class_id | name | gender | score |
---|---|---|---|---|
1 | 1 | 小明 | M | 90 |
2 | 1 | 小红 | F | 95 |
每一条记录都包含若干定义好的字段。同一个表的所有记录都有相同的字段定义。
而在关系表中,有个很重要的约束:任意两条记录不能重复,而不重复指的并非是两条记录不完全相同,而是,能够通过某个字段唯一区分出不同的记录,这个字段成为主键。
也就是说,如果Name作为主键,那么我们不能存储同名的两个不同的同学。
由于主键的该特性,通常将主键用来定位和记录,修改主键将造成较大影响,因此我们一般不对主键进行修改。为了避免修改主键,我们避免将主键设置为与任何业务相关的字段(例如身份证、手机等等),避免所有的更新换代和修改造成的不良影响。由此通常使用id来进行主键的存储。
- 自增整数类型:数据库会在插入数据时自动为每一条记录分配一个自增整数,这样我们就完全不用担心主键重复,也不用自己预先生成主键;
- 全局唯一GUID类型:使用一种全局唯一的字符串作为主键,类似
8f55d96b-8acc-4636-8cb8-76bf8abc2f57
。GUID算法通过网卡MAC地址、时间戳和随机数保证任意计算机在任意时间生成的字符串都是不同的,大部分编程语言都内置了GUID算法,可以自己预算出主键。
大部分应用使用自增整数类型即可,BIGINT NOT NULL AUTO_INCREMENT
类型。
INT自增类型上限差不多是21亿,BIGINT自增类型最多约922亿亿
联合主键
关系数据库实际上还允许通过多个字段唯一标识记录,即两个或更多的字段都设置为主键,这种主键被称为联合主键。对于联合主键,允许一列有重复,只要不是所有主键列都重复即可:
没有必要的情况下,尽量不使用联合主键,其带来关系表的复杂度的上升。
外键
以学生和班级的数据集为例对外键进行分析和介绍。
主键唯一标识记录,我们可以在students中确认任意一个学生的记录,在Classes表中确定任何一个班级的位置等。而一个班级可以有多个学生,这种一对多关系,对应的表的映射的实现,我们需要在students
表中加入class_id
,让它的值与classes
表中的某条记录相对应。
id | name | other columns |
---|---|---|
1 | 一班 | … |
2 | 二班 | … |
这样就可以通过class_id
定位出students
和classes
的对应关系,通过class_id
字段,将students
和classes
表连接起来,这种列(字段)被称为外键。
外键并不是通过列名实现的,而是通过定义外键约束实现的:
ALTER TABLE students
ADD CONSTRAINT fk_class_id
FOREIGN KEY (class_id)
REFERENCES classes (id);
其中,外键约束的名称fk_class_id
可以任意,FOREIGN KEY (class_id)
指定了class_id
作为外键,REFERENCES classes (id)
指定了这个外键将关联到classes
表的id
列(即classes
表的主键)。
通过定义外键约束,关系数据库可以保证无法插入无效的数据。即如果classes
表不存在id=99
的记录,students
表就无法插入class_id=99
的记录。
由于外键约束会降低数据库的性能,大部分互联网应用程序为了追求速度,并不设置外键约束,而是仅靠应用程序自身来保证逻辑的正确性。这种情况下,class_id
仅仅是一个普通的列,只是它起到了外键的作用而已。
删除外键约束也是通过ALTER TABLE
实现的:
ALTER TABLE students
DROP FOREIGN KEY fk_class_id;
多对多是通过一个中间表实现的。
一对一还要建表是为了避免缺省值
“关系数据库通过外键可以实现一对多、多对多和一对一的关系。外键既可以通过数据库来约束,也可以不设置约束,仅依靠应用程序的逻辑来保证。”
索引
为了快速搜索数据,需要对(用于搜索的)特定关键词建立索引,通过索引进行预排序,帮助快速定位到符合条件的记录来加快查询速度。
如果我们希望对学生的成绩score
建立索引,方便对score
进行快速查找:
ALTER TABLE students
ADD INDEX idx_score(score);
使用ADD INDEX idx_score (score)
就创建了一个名称为idx_score
,使用列score
的索引。索引名称是任意的,索引如果有多列,可以在括号里依次写上,例如:
ALTER TABLE students
ADD INDEX idx_name_score(score, name);
索引的效率取决于散列的程度,如果值越分散,索引效率越高,如果存在大量的重复值(像性别),创建索引就没有意义。
优缺点
可以对同一张表建立多个索引,但是索引的建立会带来如下的优缺点:
- 提高了查询效率
- 插入、更新、删除记录的时候需要更新,越多索引修改的速度就越慢
唯一索引
具有业务意义,如身份证之类的唯一标识,不适合作为主键,但是可以构建唯一索引,其具备最高的索引效率。
ALTER TABLE students
ADD UNIQUE INDEX uni_name(name);
也可以只对某一列添加一个唯一约束而不创建唯一索引:
ALTER TABLE students
ADD CONSTRAINT uni_name UNIQUE (name);
在这种情况下,没有建立索引,但是具备唯一性约束。