MySQL優化入門-索引簡介

MySQL優化入門-索引簡介

一.什麼是索引:

        索引用來快速尋找那些具有特定值的記錄,所有的MySQL索引都以B-樹的形式保存。例如,假設某表有1000條數據,如果沒有索引,假設要查的數據是第1000條數據,執行查詢時MySQL會從第一條記錄開始查詢,這樣要查詢1000次才能查到該數據。如果有索引,MySQL無需掃描任何記錄即可迅速得到目標記錄所在的位置,至少效率要高100倍。

二.索引分類:

2.1.主鍵索引

    主鍵是一種唯一suoy索引,它必須指定爲“PRIMARY KEY”。一般是在創建表時創建索引:例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ”。但是,我們也可以通過修改表的方式加入主鍵,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每個表只能有一個主鍵。  

參考上篇MySQL優化入門創建的存儲過程。

該表是沒有加主鍵索引:

加上索引執行:

 運行結果如下:

運行時間從1.216s提升到了0.003s,這個效率明顯提高了特別多。 

    查詢索引:

    SHOW INDEX FROM 表名;

    

 2.2.普通索引

普通索引是由關鍵字KEY或INDEX定義的索引。

create table ccc(

id int unsigned,

name varchar(32)

)

create index 索引名 on 表 (列名1,列名2);

2.3.唯一索引:

這種索引和前面的“普通索引”基本相同,但有一個區別:索引列的所有值都只能出現一次,即必須唯一。

唯一性索引可以用以下幾種方式創建: 

創建索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表); 

修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表); 

創建表的時候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) ); 

創建表結構

create table ddd(id int primary key auto_increment , name varchar(32) unique);

2.4.全文索引:

CREATE TABLE articles (

       id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,

       title VARCHAR(200),

       body TEXT,

       FULLTEXT (title,body)

     )engine=myisam charset utf8;

 

INSERT INTO articles (title,body) VALUES

     ('MySQL Tutorial','DBMS stands for DataBase ...'),

     ('How To Use MySQL Well','After you went through a ...'),

     ('Optimizing MySQL','In this tutorial we will show ...'),

     ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),

     ('MySQL vs. YourSQL','In the following database comparison ...'),

     ('MySQL Security','When configured properly, MySQL ...');

 

錯誤用法:

select * from articles where body like '%mysql%'; 錯誤用法 索引不會生效

正確用法:

select * from articles where match(title,body) against ( 'database')

說明:

  1. 在mysql中fulltext 索引只針對 myisam生效
  2. mysql自己提供的fulltext針對英文生效->sphinx (coreseek) 技術處理中文
  3. 使用方法是 match(字段名..) against(‘關鍵字’)
  4. 全文索引:停止詞,  因爲在一個文本中,創建索引是一個無窮大的數,因此,對一些常用詞和字符,就不會創建,這些詞,稱爲停止詞.比如(a,b,mysql,the)

mysql> select match(title,body) against ('database') from articles;(輸出的是每行和database的匹配度)

三.索引實現原理:

算法:二叉樹

 

 

數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用 B 樹及其變種 B+ 樹

在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

爲表設置索引要付出代價的:一是增加了數據庫的存儲空間,二是在插入和修改數據時要花費較多的時間(因爲索引也要隨之變動)。

 

上圖展示了一種可能的索引方式。左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址(注意邏輯上相鄰的記錄在磁盤上也並不是一定物理相鄰的)。爲了加快 Col2 的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在 O(log2n)的複雜度內獲取到相應數據。

創建索引可以大大提高系統的性能。

第一,通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。

第二,可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。

第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。

第四,在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。

第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

也許會有人要問:增加索引有如此多的優點,爲什麼不對錶中的每一個列創建一個索引呢?因爲,增加索引也有許多不利的方面。

第一,創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加。

第二,索引需要佔物理空間,除了數據表佔數據空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。

第三,當對錶中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。

索引是建立在數據庫表中的某些列的上面。在創建索引的時候,應該考慮在哪些列上可以創建索引,在哪些列上不能創建索引。一般來說,應該在這些列上創建索引:在經常需要搜索的列上,可以加快搜索的速度;在作爲主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,其指定的範圍是連續的;在經常需要排序的列上創建索引,因爲索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;在經常使用在 WHERE 子句中的列上面創建索引,加快條件的判斷速度。

同樣,對於有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:

第一,對於那些在查詢中很少使用或者參考的列不應該創建索引。這是因爲,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。

第二,對於那些只有很少數據值的列也不應該增加索引。這是因爲,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,並不能明顯加快檢索速度。

第三,對於那些定義爲 text, image 和 bit 數據類型的列不應該增加索引。這是因爲,這些列的數據量要麼相當大,要麼取值很少。

第四,當修改性能遠遠大於檢索性能時,不應該創建索引。這是因爲,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引。

根據數據庫的功能,可以在數據庫設計器中創建三種索引:唯一索引、主鍵索引和聚集索引

唯一索引

唯一索引是不允許其中任何兩行具有相同索引值的索引。

當現有數據中存在重複的鍵值時,大多數數據庫不允許將新創建的唯一索引與表一起保存。數據庫還可能防止添加將在表中創建重複鍵值的新數據。例如,如果在 employee 表中職員的姓(lname)上創建了唯一索引,則任何兩個員工都不能同姓。主鍵索引數據庫表經常有一列或列組合,其值唯一標識表中的每一行。該列稱爲表的主鍵。在數據庫關係圖中爲表定義主鍵將自動創建主鍵索引,主鍵索引是唯一索引的特定類型。該索引要求主鍵中的每個值都唯一。當在查詢中使用主鍵索引時,它還允許對數據的快速訪問。聚集索引在聚集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個聚集索引。

如果某索引不是聚集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非聚集索引相比,聚集索引通常提供更快的數據訪問速度。

局部性原理與磁盤預讀

由於存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分分之一,因此爲了提高效率,要儘量減少磁盤 I/O。爲了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向後讀取一定長度的數據放入內存。這樣做的理論依據是計算機科學中著名的局部性原理當一個數據被用到時,其附近的數據也通常會馬上被使用。程序運行期間所需要的數據通常比較集中。

由於磁盤順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有局部性的程序來說,預讀可以提高 I/O 效率。

預讀的長度一般爲頁(page)的整倍數。頁是計算機管理存儲器的邏輯塊,硬件及操作系統往往將主存和磁盤存儲區分割爲連續的大小相等的塊,每個存儲塊稱爲一頁(在許多操作系統中,頁得大小通常爲 4k),主存和磁盤以頁爲單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置並向後連續讀取一頁或幾頁載入內存中,然後異常返回,程序繼續運行。

B-/+Tree 索引的性能分析

到這裏終於可以分析 B-/+Tree 索引的性能了。

上文說過一般使用磁盤 I/O 次數評價索引結構的優劣。先從 B-Tree 分析,根據 B-Tree 的定義,可知檢索一次最多需要訪問 h 個節點。數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每個節點只需要一次 I/O 就可以完全載入。爲了達到這個目的,在實際實現 B-Tree 還需要使用如下技巧:

每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁裏,加之計算機存儲分配都是按頁對齊的,就實現了一個 node 只需一次 I/O。

B-Tree 中一次檢索最多需要 h-1 次 I/O(根節點常駐內存),漸進複雜度爲 O(h)=O(logdN)。一般實際應用中,出度 d 是非常大的數字,通常超過 100,因此 h 非常小(通常不超過 3)。

而紅黑樹這種結構,h 明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,所以紅黑樹的 I/O 漸進複雜度也爲 O(h),效率明顯比 B-Tree 差很多。

綜上所述,用 B-Tree 作爲索引結構效率是非常高的。

應該花時間學習 B-樹和 B+ 樹數據結構

=============================================================================================================

1)B 樹

B 樹中每個節點包含了鍵值和鍵值對於的數據對象存放地址指針,所以成功搜索一個對象可以不用到達樹的葉節點。

成功搜索包括節點內搜索和沿某一路徑的搜索,成功搜索時間取決於關鍵碼所在的層次以及節點內關鍵碼的數量。

在 B 樹中查找給定關鍵字的方法是:首先把根結點取來,在根結點所包含的關鍵字 K1,…,kj 查找給定的關鍵字(可用順序查找或二分查找法),若找到等於給定值的關鍵字,則查找成功;否則,一定可以確定要查的關鍵字在某個 Ki 或 Ki+1 之間,於是取 Pi 所指的下一層索引節點塊繼續查找,直到找到,或指針 Pi 爲空時查找失敗。

2)B+ 樹

B+ 樹非葉節點中存放的關鍵碼並不指示數據對象的地址指針,非也節點只是索引部分。所有的葉節點在同一層上,包含了全部關鍵碼和相應數據對象的存放地址指針,且葉節點按關鍵碼從小到大順序鏈接。如果實際數據對象按加入的順序存儲而不是按關鍵碼次數存儲的話,葉節點的索引必須是稠密索引,若實際數據存儲按關鍵碼次序存放的話,葉節點索引時稀疏索引。

B+ 樹有 2 個頭指針,一個是樹的根節點,一個是最小關鍵碼的葉節點。

所以 B+ 樹有兩種搜索方法:

一種是按葉節點自己拉起的鏈表順序搜索。

一種是從根節點開始搜索,和 B 樹類似,不過如果非葉節點的關鍵碼等於給定值,搜索並不停止,而是繼續沿右指針,一直查到葉節點上的關鍵碼。所以無論搜索是否成功,都將走完樹的所有層。

B+ 樹中,數據對象的插入和刪除僅在葉節點上進行。

這兩種處理索引的數據結構的不同之處:
a,B 樹中同一鍵值不會出現多次,並且它有可能出現在葉結點,也有可能出現在非葉結點中。而 B+ 樹的鍵一定會出現在葉結點中,並且有可能在非葉結點中也有可能重複出現,以維持 B+ 樹的平衡。
b,因爲 B 樹鍵位置不定,且在整個樹結構中只出現一次,雖然可以節省存儲空間,但使得在插入、刪除操作複雜度明顯增加。B+ 樹相比來說是一種較好的折中。
c,B 樹的查詢效率與鍵在樹中的位置有關,最大時間複雜度與 B+ 樹相同(在葉結點的時候),最小時間複雜度爲 1(在根結點的時候)。而 B+ 樹的時候複雜度對某建成的樹是固定的。可以掃描2的次方。

四.索引的代價:

  1. 佔用磁盤空間;
  2. 對DML(update、delete、insert) 語句效率有影響;
  3. 增刪改對索引有影響,索引需要重新整理。

存儲引擎

允許的索引類型

myisam

btree

innodb

btree

memory/yeap

Hash,btree

 哪些列上適合加索引?

  • 查詢作爲查詢條件字段應該創建索引
  • 唯一性太差的字段不適合單獨創建索引,即使頻繁
  • 頻繁更新字段,也不要定義索引。
  • 不會出現在where語句的字段不要創建索引

總結:滿處一下條件的字段,才應該創建索引

  • 肯定在where條件經常使用
  • 該字段的內容不是唯一的幾個值 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章