MySQL索引分析和優化

2021-05-23 21:15:36 字數 4620 閱讀 1534

什麼是索引?

索引用來快速地尋找那些具有特定值的記錄,所有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命令為「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 unique index 《索引的名字》 on tablename (列的列表);

修改表,例如alter table tablename add unique [索引的名字] (列的列表);

建立表的時候指定索引,例如create table tablename ( [...], unique [索引的名字] (列的列表)

);

主鍵

主鍵是一種唯一性索引,但它必須指定為「primary key」。如果你曾經用過auto_increment型別的列,你可能已經熟悉主鍵之類的概念了。主鍵一般在建立表的時候指定,例如「create table tablename ( [...], primary key (列的列表) ); 」。但是,我們也可以通過修改表的方式加入主鍵,例如「alter table tablename add primary key (列的列表); 」。每個表只能有乙個主鍵。

全文索引單列索引與多列索引

索引可以是單列索引,也可以是多列索引。下面我們通過具體的例子來說明這兩種索引的區別。假設有這樣乙個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(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就返回最終的搜尋結果。

由於建立了firstname列的索引,與執行表的完全掃瞄相比,mysql的效率提高了很多,但我們要求mysql掃瞄的記錄數量仍舊遠遠超過了實際所需要的。雖然我們可以刪除firstname列上的索引,再建立lastname或者age列的索引,但總地看來,不論在哪個列上建立索引搜尋效率仍舊相似。

為了提高搜尋效率,我們需要考慮運用多列索引。如果為firstname、lastname和age這三個列建立乙個多列索引,mysql只需一次檢索就能夠找出正確的結果!下面是建立這個多列索引的sql命令:

alter table people add index fname_lname_age (firstname,lastname,age);
最左字首

多列索引還有另外乙個優點,它通過稱為最左字首(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'; 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';

選擇索引列

在效能優化過程中,選擇在哪些列上建立索引是最重要的步驟之一。可以考慮使用索引的主要有兩種型別的列:在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子句中,因此我們需要考慮建立該列的索引。

MySQL索引分析和優化

索引 索引用來快速地尋找那些具備特定值的記錄,任何mysql索引都以b 樹的形式儲存。假如沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的任何記錄,直至找到符合需要的記錄。表裡面的記錄數量越多,這個操作的代價就越高。假如作為搜尋條件的列上已建立了索引,mysql無需掃瞄任何記錄即可迅速...

MySQL索引分析和優化 什麼是索引?

mysql索引分析和優化 什麼是索引?索引用來快速地尋找那些具有特定值的記錄,所有mysql索引都以b 樹的形式儲存。如果沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,...

MySQL索引優化分析

1.通過訂單號查詢某個訂單,用唯一索引 資料量幾百萬以上 2.order by 排序時,後面欄位加 強制指定索引 select from orderforce index idx ordere order by order level,input date 哪些情況需要建索引 1 主鍵,唯一索引 2...