數據庫學習篇三

外鍵的理解

當我們用主鍵唯一標識記錄時,我們就可以在students表中確定任意一個學生的記錄:

id	name	other columns...
1	小明	       ...
2	小紅	       ...

我們還可以在classes表中確定任意一個班級記錄:

id	name	other columns...
1	一班	     ...
2	二班	     ...

但是我們如何確定students表的一條記錄,例如,id=1的小明,屬於哪個班級呢?由於一個班級可以有多個學生,在關係模型中,這兩個表的關係可以稱爲“一對多”,即一個classes的記錄可以對應多個students表的記錄。

爲了表達這種一對多的關係,我們需要在students表中加入一列class_id,讓它的值與classes表的某條記錄相對應:

id	class_id	name	other columns...
1	  1	        小明	      ...
2	  1	        小紅	      ...
5	  2	        小白	      ...

這樣,我們就可以根據class_id這個列直接定位出一個students表的記錄應該對應到classes的哪條記錄。例如:
小明的class_id是1,因此,對應的classes表的記錄是id=1的一班;
小紅的class_id是1,因此,對應的classes表的記錄是id=1的一班;
小白的class_id是2,因此,對應的classes表的記錄是id=2的二班。
在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 ...實現的。

多對多與一對一關係的理解

多對多關係:
通過一個表的外鍵關聯到另一個表,我們可以定義出一對多關係。有些時候,還需要定義**“多對多”**關係。例如,一個老師可以對應多個班級,一個班級也可以對應多個老師,因此,班級表和老師表存在多對多關係。
多對多關係實際上是通過兩個一對多關係實現的,即通過一箇中間表,關聯兩個一對多關係,就形成了多對多關係:
teachers表:

id	name
1	張老師
2	王老師
3	李老師
4	趙老師

classes表:

id	name
1	一班
2	二班

中間表teacher_class關聯兩個一對多關係:

id	teacher_id	class_id
1	    1	       1
2	    1	       2
3	    2	       1
4	    2          2
5	    3	       1
6	    4	       2

通過中間表teacher_class可知teachers到classes的關係:
id=1的張老師對應id=1,2的一班和二班;
id=2的王老師對應id=1,2的一班和二班;
id=3的李老師對應id=1的一班;
id=4的趙老師對應id=2的二班。
同理可知classes到teachers的關係:
id=1的一班對應id=1,2,3的張老師、王老師和李老師;
id=2的二班對應id=1,2,4的張老師、王老師和趙老師;
因此,通過中間表,我們就定義了一個“多對多”關係。

一對一關係:
一對一關係是指,一個表的記錄對應到另一個表的唯一一個記錄。
例如,students表的每個學生可以有自己的聯繫方式,如果把聯繫方式存入另一個表contacts,我們就可以得到一個“一對一”關係:

id	student_id	mobile
1	    1	135xxxx6300
2	    2	138xxxx2209
3	    5	139xxxx8086

既然是一對一關係,那爲啥不給students表增加一個mobile列,這樣就能合二爲一了?
如果業務允許,完全可以把兩個表合爲一個表。但是,有些時候,如果某個學生沒有手機號,那麼,contacts表就不存在對應的記錄。實際上,一對一關係準確地說,是contacts表一對一對應students表。
還有一些應用會把一個大表拆成兩個一對一的表,目的是把經常讀取和不經常讀取的字段分開,以獲得更高的性能。例如,把一個大的用戶表分拆爲用戶基本信息表user_info和用戶詳細信息表user_profiles,大部分時候,只需要查詢user_info表,並不需要查詢user_profiles表,這樣就提高了查詢速度。

索引的理解

在關係數據庫中,如果有上萬甚至上億條記錄,在查找記錄的時候,想要獲得非常快的速度,就需要使用索引。
**索引是關係數據庫中對某一列或多個列的值進行預排序的數據結構。**通過使用索引,可以讓數據庫系統不必掃描整個表,而是直接定位到符合條件的記錄,這樣就大大加快了查詢速度。
例如,對於students表:

id	class_id	name	gender	score
1	1	         小明	   M	90
2	1	         小紅	   F	95
3	1	         小軍	   M	88

如果要經常根據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列沒有索引,但仍然具有唯一性保證。其實無論是否創建索引,對於用戶和應用程序來說,使用關係數據庫不會有任何區別。這裏的意思是說,當我們在數據庫中查詢時,如果有相應的索引可用,數據庫系統就會自動使用索引來提高查詢效率,如果沒有索引,查詢也能正常執行,只是速度會變慢。因此,索引可以在使用數據庫的過程中逐步優化。

總結

關係數據庫通過外鍵可以實現一對多、多對多和一對一的關係,外鍵既可以通過數據庫來約束,也可以不設置約束,僅依靠應用程序的邏輯來保證。同時通過對數據庫表創建索引,可以提高查詢速度,通過創建唯一索引,可以保證某一列的值具有唯一性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章