討論mysql選擇索引時單列單列索引和多列索引使用,以及多列索引的最左字首原則。
1. 單列索引
在效能優化過程中,選擇在哪些列上建立索引是最重要的步驟之一。可以考慮使用索引的主要有兩種型別的列:在where子句中出現的列,在join子句中出現的列。請看下面這個查詢:
select age ## 不使用索引
from people where firstname='mike' ## 考慮使用索引
and lastname='sullivan' ## 考慮使用索引
這個查詢與前面的查詢略有不同,但仍屬於簡單查詢。由於age是在select部分被引用,mysql不會用它來限制列選擇操作。因此,對於這個查詢來說,建立age列的索引沒有什麼必要。
下面是乙個更複雜的例子:
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子句中,因此我們需要考慮建立該列的索引。
那麼,我們是否可以簡單地認為應該索引where子句和join子句中出現的每乙個列呢?差不多如此,但並不完全。我們還必須考慮到對列進行比較的操作符型別。mysql只有對以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like。
可以在like操作中使用索引的情形是指另乙個運算元不是以萬用字元(%或者_)開頭的情形。
例如:
select peopleid from people where firstname like 'mich%'
這個查詢將使用索引;但下面這個查詢不會使用索引。
select peopleid from people where firstname like '%ike';
2. 多列索引
索引可以是單列索引,也可以是多列索引。下面我們通過具體的例子來說明這兩種索引的區別。假設有這樣乙個people表:
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) );
下面是我們插入到這個people表的資料:
這個資料片段中有四個名字為「mikes」的人(其中兩個姓sullivans,兩個姓mcconnells),有兩個年齡為17歲的人,還有乙個名字與眾不同的joe smith。
這個表的主要用途是根據指定的使用者姓、名以及年齡返回相應的peopleid。例如,我們可能需要查詢姓名為mike sullivan、年齡17歲使用者的peopleid:
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就返回最終的搜尋結果。
由於建立了firstname列的索引,與執行表的完全掃瞄相比,mysql的效率提高了很多,但我們要求mysql掃瞄的記錄數量仍舊遠遠超過了實際所需要的。雖然我們可以刪除firstname列上的索引,再建立lastname或者age列的索引,但總地看來,不論在哪個列上建立索引搜尋效率仍舊相似。
為了提高搜尋效率,我們需要考慮運用多列索引。如果為firstname、lastname和age這三個列建立乙個多列索引,mysql只需一次檢索就能夠找出正確的結果!下面是建立這個多列索引的sql命令:
alter table people
add index fname_lname_age (firstname,lastname,age);
由於索引檔案以b-樹格式儲存,mysql能夠立即轉到合適的firstname,然後再轉到合適的lastname,最後轉到合適的age。在沒有掃瞄資料檔案任何乙個記錄的情況下,mysql就正確地找出了搜尋的目標記錄!
那麼,如果在firstname、lastname、age這三個列上分別建立單列索引,效果是否和建立乙個firstname、lastname、age的多列索引一樣呢?
3. 多列索引中最左字首(leftmost prefixing)
多列索引還有另外乙個優點,它通過稱為最左字首(leftmost prefixing)的概念體現出來。繼續考慮前面的例子,現在我們有乙個firstname、lastname、age列上的多列索引,我們稱這個索引為fname_lname_age。當搜尋條件是以下各種列的組合時,mysql將使用fname_lname_age索引:
firstname,lastname,age
firstname,lastname
firstname
從另一方面理解,它相當於我們建立了(firstname,lastname,age)、(firstname,lastname)以及(firstname)這些列組合上的索引。下面這些查詢都能夠使用這個fname_lname_age索引:
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';
下面這些查詢不能夠使用這個fname_lname_age索引:
select peopleid from people
where lastname='sullivan';
select peopleid from people
where age='17';
select peopleid from people
where lastname='sullivan' and age='17';
MySQL單列索引和多列索引
在設計mysql表索引的時候,可能有個問題,就是多個單列索引好,還是設計為多列索引好 下面從不同角度分析下這個問題 1.多個單列索引 定義 即是在表中在需要索引的字段上為每個字段設計乙個索引 特點 簡單,索引個數多 2.多列索引 定義 即是在表中根據查詢需求在多個欄位上設計乙個索引 特點 稍微複雜,...
mysql單列索引 多列索引的使用
資料庫的索引可以加快查詢速度,原因是索引使用特定的資料結構 b tree 對特定的列額外組織存放,加快儲存引擎 索引是儲存引擎實現 查詢記錄的速度。索引優化是資料庫優化的最重要手段。如果查詢語句使用索引 通常是where條件匹配索引 就會利用樹的結構加快查詢,索引會按值查詢到要查詢的行在表中位置,不...
mysql 單列索引與多列索引
以下的文章主要介紹的是mysql資料庫索引型別,其中包括普通索引,唯一索引,主鍵索引與主鍵索引,以及對這些索引的實際應用或是建立有乙個詳細介紹,以下就是文章的主要內容描述。1 普通索引 這是最基本的mysql資料庫索引,它沒有任何限制。它有以下幾種建立方式 建立索引 create index ind...