對于索引中的每一項,MySQL在內部為它保存一個數據文件中實際記錄所在位置的“指針”。因此,如果我們要查找name等于“Mike”記錄的peopleid(SQL命令為“SELECT peopleid FROM people WHERE name='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 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) );
這個表的主要用途是根據指定的用戶姓、名以及年齡返回相應的peopleid。例如,我們可能需要查找姓名為Mike Sullivan、年齡17歲用戶的peopleid(SQL命令為SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age=17;)。由于我們不想讓MySQL每次執行查詢就去掃描整個表,這里需要考慮運用索引。
首先,我們可以考慮在單個列上創建索引,比如firstname、lastname或者age列。如果我們創建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL將通過這個索引迅速把搜索范圍限制到那些firstname='Mike'的記錄,然后再在這個“中間結果集”上進行其他條件的搜索:它首先排除那些lastname不等于“Sullivan”的記錄,然后排除那些age不等于17的記錄。當記錄滿足所有搜索條件之后,MySQL就返回最終的搜索結果。
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 people.age, ##不使用索引 town.name ##不使用索引 FROM people LEFT JOIN town ON people.townid=town.townid ##考慮使用索引 WHERE firstname='Mike' ##考慮使用索引 AND lastname='Sullivan' ##考慮使用索引
那么,我們是否可以簡單地認為應該索引WHERE子句和join子句中出現的每一個列呢?差不多如此,但并不完全。我們還必須考慮到對列進行比較的操作符類型。MySQL只有對以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE。可以在LIKE操作中使用索引的情形是指另一個操作數不是以通配符(%或者_)開頭的情形。例如,“SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';”這個查詢將使用索引,但“SELECT peopleid FROM people WHERE firstname LIKE '%ike';”這個查詢不會使用索引。