1、索引(index)
索引类似于目录,根据索引进行查询可大大增加检索数据的效率。但是存储索引需要一定的内存,而且当数据修改时也要对索引进行维护,成本较高,所以不能随意地添加索引。
当出现以下情况时,可以考虑给字段添加索引:
- 表中数据量庞大
- 字段经常被检索,即出现在
where
语句中的字段 - 很少对字段进行修改
MySQL中可通过show index from 表名;
查看当前表中添加索引的字段,建立和删除索引的语句分别为:create index 索引名 on 表名(字段名);
、drop index 索引名 on 表名;
,下面通过有无索引的查询比较说明性能优劣。
//假设有员工表emp
mysql> desc emp;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO | int(4) | NO | PRI | NULL | |
| ENAME | varchar(10) | YES | | NULL | |
| JOB | varchar(9) | YES | | NULL | |
| MGR | int(4) | YES | | NULL | |
| HIREDATE | date | YES | | NULL | |
| SAL | double(7,2) | YES | | NULL | |
| COMM | double(7,2) | YES | | NULL | |
| DEPTNO | int(2) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
//无索引查询工资为5000的员工信息,查询了14条记录
mysql> explain select * from emp where sal=5000;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 14 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
//有索引查询工资为5000的员工信息,查询了1条记录
mysql> create index emp_sal on emp(sal);
mysql> explain select * from emp where sal=5000;
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | emp | NULL | ref | emp_sal | emp_sal | 9 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
需要注意的是具有主键约束和唯一约束的字段默认添加索引,分别称为主键索引
、唯一索引
,除此之外,和单一索引
相对的是复合索引
。
根据复合索引进行查询的效果好坏依赖查询语句,好比有两个字段姓和名建立了复合索引,单纯的查名与没有索引效果一样,查姓和姓名都会提高速度,这与索引的底层实现原理—B+树
的建立有关。
2、视图(view)
视图可以理解为将表中的部分数据拿出来当作一张虚拟表,通过操作视图里的数据从而达到修改原表数据的目的。这样做的好处就是可以隐藏表的实现细节,做到数据的保密。
创建和删除视图的语句分别为:create view 视图名 as select语句;
、drop view 视图名
。
//创建视图,由emp表部分字段构成
mysql> create view emp_view as select ename,sal from emp;
//修改视图中的数据
mysql> select * from emp where ename='KING';
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
+-------+-------+-----------+------+------------+---------+------+--------+
mysql> update emp_view set sal=6000 where ename='KING';
//原表数据随之修改
mysql> select * from emp where ename='KING';
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 6000.00 | NULL | 10 |
+-------+-------+-----------+------+------------+---------+------+--------+
3、数据库设计三范式
设计表的过程中要根据设计范式
,以防止出现数据冗余的情况。
1、第一范式
任何一张表都应该有主键,且每个字段原子性不可再分。
如果有员工表如下,显然有两个问题:员工编号重复,给后续工作带来麻烦;联系方式中邮箱和电话没有分为两个字段。
员工编号 | 员工姓名 | 联系方式 |
1 | Alice | 邮箱、电话 |
1 | Bob | 邮箱、电话 |
2、第二范式
在第一范式的基础上,要求所有非主键字段完全依赖主键,不能产生部分依赖。
往往采用复合主键时会出现部分依赖现象,不同的字段依赖复合主键的部分主键,这就涉及到多对多
关系的表设计:设计2张具有依赖关系的表和1张关系表,其中关系表采用两个外键。例如学生表(学号、姓名)以及课程表(课程编号、课程名称)的设计。
3、第三范式
在第二范式的基础上,要求所有非主键字段不能传递依赖于主键。
第三范式涉及到一对多
关系的表设计:设计2张具有依赖关系的表,其中‘多’的那张表采用一个外键。例如学生表(学号、姓名)以及班级表(班级编号、班级名称)的设计。
具有一对一
关系的表理论上设计成一张表即可,但是实际应用中可能对表的一部分数据经常查询,另外一部分可作为补充信息,这个时候就要设计成多张表。
一对一
关系的表有两种设计方案:主键共享、外键唯一:
- 主键共享:在分开的两张表中都添加一个字段作为主键,比如序号,其中一个主键再作为外键(信息来源于另外一个主键);
- 外键唯一:在分开的两张表中都添加一个相同含义的字段,比如序号,其中一张表中的该字段既是外键(信息来源于另外一张表的相同含义字段)又唯一(
unique
)。