轉自:http://blog.csdn.net/duck_arrow/article/details/8264686html
概念:數據庫
主鍵(primary key) 可以惟一標識表中某一行的屬性或屬性組。一個表只能有一個主鍵,但能夠有多個候選索引。主鍵經常與外鍵構成參照完整性約束,防止出現數據不一致。主鍵能夠保證記錄的惟一和主鍵域非空,數據庫管理系統對於主鍵自動生成惟一索引,因此主鍵也是一個特殊的索引。性能優化
外鍵(foreign key) 是用於創建和增強兩個表數據之間的連接的一列或多列。外鍵約束主要用來維護兩個表之間數據的一致性。簡言之,表的外鍵就是另外一表的主鍵,外鍵將兩表聯繫起來。通常狀況下,要刪除一張表中的主鍵必須首先要確保其它表中的沒有相同外鍵(即該表中的主鍵沒有一個外鍵和它相關聯)。性能
索引(index) 是用來快速地尋找那些具備特定值的記錄。主要是爲了檢索的方便,是爲了加快訪問速度, 按必定的規則建立的,通常起到排序做用。所謂惟一性索引,這種索引和前面的「普通索引」基本相同,但有一個區別:索引列的全部值都只能出現一次,即必須惟一。優化
總結:spa
主鍵必定是惟一性索引,惟一性索引並不必定就是主鍵。.net
一個表中能夠有多個惟一性索引,但只能有一個主鍵。指針
主鍵列不容許空值,而惟一性索引列容許空值。code
主鍵能夠被其餘字段做外鍵引用,而索引不能做爲外鍵引用。htm
主鍵:
主鍵是數據表的惟一索引,好比學生表裏有學號和姓名,姓名可能有重名的,但學號確是惟一的,你要從學生表中搜索一條紀錄如查找一我的,就只能根據學號去查找,這才能找出惟一的一個,這就是主鍵;如:idint(10) not null primary key auto_increment ;自增加的類型 ;
外鍵:
定義數據表
假如某個電腦生產商,它的數據庫中保存着整機和配件的產品信息。用來保存整機產品信息的表叫作Pc;用來保存配件供貨信息的表叫作Parts。
在Pc表中有一個字段,用來描述這款電腦所使用的CPU型號;
在Parts 表中相應有一個字段,描述的正是CPU的型號,咱們能夠把它想成是所有CPU的型號列表。
很顯然,這個廠家生產的電腦,其使用的CPU必定是供貨信息表(parts)中存在的型號。這時,兩個表中就存在一種約束關係(constraint)——Pc表中的CPU型號受到Parts表中型號的約束。
首先咱們來建立 parts 表:
CREATE TABLE parts (
... 字段定義 ...,
model VARCHAR(20) NOT NULL,
... 字段定義 ...
);
接下來是Pc表:
CREATE TABLE pc (
... 字段定義 ...,
cpumodel VARCHAR(20) NOT NULL,
... 字段定義 ...
};
設置索引
若要設置外鍵,在參照表(referencing table,即Pc表) 和被參照表 (referencedtable,即parts表) 中,相對應的兩個字段必須都設置索引(index)。
對Parts表:
ALTER TABLE parts ADD INDEX idx_model (model);
這句話的意思是,爲 parts 表增長一個索引,索引創建在 model字段上,給這個索引發個名字叫idx_model。
對Pc表也相似:
ALTER TABLE pc ADD INDEX idx_cpumodel (cpumodel);
事實上這兩個索引能夠在建立表的時候就設置。這裏只是爲了突出其必要性。
定義外鍵
下面爲兩張表之間創建前面所述的那種「約束」。由於pc的CPU型號必須參照parts表中的相應型號,因此咱們將Pc表的cpumodel字段設置爲「外鍵」(FOREIGNKEY),即這個鍵的參照值來自於其餘表。
ALTER TABLE pc ADD CONSTRAINT fk_cpu_model
FOREIGN KEY (cpumodel)
REFERENCES parts(model);
第一行是說要爲Pc表設置外鍵,給這個外鍵起一個名字叫作fk_cpu_model;第二行是說將本表的cpumodel字段設置爲外鍵;第三行是說這個外鍵受到的約束來自於Parts表的model字段。
這樣,咱們的外鍵就能夠了。若是咱們試着CREATE一臺Pc,它所使用的CPU的型號是Parts表中不存在的,那麼MySQL會禁止這臺PC被CREATE出來。
級聯操做
考慮如下這種狀況:
技術人員發現,一個月以前輸入到 parts 表中的某個系列的 cpu(可能有不少款)的型號全都輸錯了一個字母,如今須要改正。咱們但願的是,當 parts 表中那些 Referenced Column有所變化時,相應表中的 Referencing Column 也能自動更正。
能夠在定義外鍵的時候,在最後加入這樣的關鍵字:
ON UPDATE CASCADE;即在主表更新時,子表(們)產生連鎖更新動做,彷佛有些人喜歡把這個叫「級聯」操做。:)
若是把這語句完整的寫出來,就是:
ALTER TABLE pc ADD CONSTRAINT fk_cpu_model
FOREIGN KEY (cpumodel)
REFERENCES parts(model)
ON UPDATE CASCADE;
除了 CASCADE 外,還有 RESTRICT(禁止主表變動)、SET NULL(子表相應字段設置爲空)等操做
索引:
索引用來快速地尋找那些具備特定值的記錄,全部MySQL索引都以B-樹的形式保存。若是沒有索引,執行查詢時MySQL必須從第一個記錄開始掃描整個表的全部記錄,直至找到符合要求的記錄。表裏面的記錄數量越多,這個操做的代價就越高。若是做爲搜索條件的列上已經建立了索引,MySQL無需掃描任何記錄便可迅速獲得目標記錄所在的位置。若是表有1000個記錄,經過索引查找記錄至少要比順序掃描記錄快100倍。
假設咱們建立了一個名爲people的表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL ); |
而後,咱們徹底隨機把1000個不一樣name值插入到people表。下圖顯示了people表所在數據文件的一小部分:
能夠看到,在數據文件中name列沒有任何明確的次序。若是咱們建立了name列的索引,MySQL將在索引中排序name列:
對於索引中的每一項,MySQL在內部爲它保存一個數據文件中實際記錄所在位置的「指針」。所以,若是咱們要查找name等於「Mike」記錄的peopleid(SQL命令爲「SELECTpeopleid FROM people WHEREname='Mike';」),MySQL可以在name的索引中查找「Mike」值,而後直接轉到數據文件中相應的行,準確地返回該行的peopleid(999)。在這個過程當中,MySQL只需處理一個行就能夠返回結果。若是沒有「name」列的索引,MySQL要掃描數據文件中的全部記錄,即1000個記錄!顯然,須要MySQL處理的記錄數量越少,則它完成任務的速度就越快。索引的類型
MySQL提供多種索引類型供選擇:
普通索引
這是最基本的索引類型,並且它沒有惟一性之類的限制。普通索引能夠經過如下幾種方式建立:
建立索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表); 建立表的時候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) ); |
惟一性索引
這種索引和前面的「普通索引」基本相同,但有一個區別:索引列的全部值都只能出現一次,即必須惟一。惟一性索引能夠用如下幾種方式建立:
建立索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表); 建立表的時候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) ); |
主鍵
主鍵是一種惟一性索引,但它必須指定爲「PRIMARYKEY」。若是你曾經用過AUTO_INCREMENT類型的列,你可能已經熟悉主鍵之類的概念了。主鍵通常在建立表的時候指定,例如「CREATETABLE tablename ( [...], PRIMARY KEY (列的列表) );」。可是,咱們也能夠經過修改表的方式加入主鍵,例如「ALTER TABLE tablename ADD PRIMARY KEY(列的列表); 」。每一個表只能有一個主鍵。
全文索引
MySQL從3.23.23版開始支持全文索引和全文檢索。在MySQL中,全文索引的索引類型爲FULLTEXT。全文索引能夠在VARCHAR或者TEXT類型的列上建立。它能夠經過CREATETABLE命令建立,也能夠經過ALTER TABLE或CREATE INDEX命令建立。對於大規模的數據集,經過ALTERTABLE(或者CREATEINDEX)命令建立全文索引要比把記錄插入帶有全文索引的空表更快。本文下面的討論再也不涉及全文索引,要了解更多信息,請參見MySQLdocumentation。
CREATE TABLE people ( peopleid SMALLINT NOT NULL AUTO_INCREMENT, firstname CHAR(50) NOT NULL, lastname CHAR(50) NOT NULL, age SMALLINT NOT NULL, townid SMALLINT NOT NULL, PRIMARY KEY (peopleid) ); |
ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age); |
firstname,lastname,age firstname,lastname firstname |
SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan'; SELECT peopleid FROM people WHERE firstname='Mike'; The following queries cannot use the index at all: SELECT peopleid FROM people WHERE lastname='Sullivan'; SELECT peopleid FROM people WHERE age='17'; SELECT peopleid FROM people WHERE lastname='Sullivan' AND age='17'; |
SELECT age ## 不使用索引 FROM people WHERE firstname='Mike' ## 考慮使用索引 AND lastname='Sullivan' ## 考慮使用索引 |
SELECT people.age, ##不使用索引 town.name ##不使用索引 FROM people LEFT JOIN town ON people.townid=town.townid ##考慮使用索引 WHERE firstname='Mike' ##考慮使用索引 AND lastname='Sullivan' ##考慮使用索引 |
與前面的例子同樣,因爲firstname和lastname出如今WHERE子句中,所以這兩個列仍舊有建立索引的必要。除此以外,因爲town表的townid列出如今join子句中,所以咱們須要考慮建立該列的索引。
惟一索引:
通索引容許被索引的數據列包含重複的值。好比說,由於人有可能同名,因此同一個姓名在同一個「員工我的資料」數據表裏可能出現兩次或更屢次。
若是能肯定某個數據列將只包含彼此各不相同的值,在爲這個數據列建立索引的時候就應該用關鍵字UNIQUE把它定義爲一個惟一索引。這麼作的好處:一是簡化了MySQL對這個索引的管理工做,這個索引也所以而變得更有效率;二是MySQL會在有新記錄插入數據表時,自動檢查新記錄的這個字段的值是否已經在某個記錄的這個字段裏出現過了;若是是,MySQL將拒絕插入那條新記錄。也就是說,惟一索引能夠保證數據記錄的惟一性。事實上,在許多場合,人們建立惟一索引的目的每每不是爲了提升訪問速度,而只是爲了不數據出現重複