06 关系模型

外键

在 students 表中,通过 class_id 的字段,可以把数据与另一张表关联起来,这种列称为外键。

外键并不是通过列名实现的,而是通过定义外键约束实现的:

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;

注意:删除外键约束并没有删除外键这一列。删除列是通过 DROP COLUMN 实现的。

索引

索引是关系数据库中对某一列或多个列的值进行预排序的数据结构。通过使用索引,可以让数据库系统不必扫描整个表,而是直接定位到符合条件的记录,这样就大大加快了查询速度。

对于 students 表,如果要经常根据 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 (name, score);

索引的效率取决于索引列的值是否散列,即该列的值如果越互不相同,那么索引效率越高。反过来,如果记录的列存在大量相同的值,例如 gender 列,大约一半的记录值是 M,另一半是 F,因此,对该列创建索引就没有意义。

在设计关系数据表的时候,看上去唯一的列,例如身份证号、邮箱地址等,因为他们具有业务含义,因此不宜作为主键。但是,这些列根据业务要求,又具有唯一性约束:即不能出现两条记录存储了同一个身份证号。这个时候,就可以给该列添加一个唯一索引。例如,我们假设 students 表的 name 不能重复:

ALTER TABLE students
ADD UNIQUE INDEX uni_name (name);

通过 UNIQUE 关键字我们就添加了一个唯一索引。

也可以只对某一列添加一个唯一约束而不创建唯一索引:

ALTER TABLE students
ADD CONSTRAINT uni_name UNIQUE (name);

这种情况下,name 列没有索引,但仍然具有唯一性保证。

无论是否创建索引,对于用户和应用程序来说,使用关系数据库不会有任何区别。这里的意思是说,当我们在数据库中查询时,如果有相应的索引可用,数据库系统就会自动使用索引来提高查询效率,如果没有索引,查询也能正常执行,只是速度会变慢。因此,索引可以在使用数据库的过程中逐步优化。