《高性能SQL調優精要與案例解析》一書談主流關係庫SQL調優(SQL TUNING或SQL優化)核心機制之——索引(index)

繼《高性能SQL調優精要與案例解析》一書談SQL調優(SQL TUNING或SQL優化),咱們今天就談談各主流關係庫中,佔據SQL調優技術和工做半壁江山的、最重要的核心機制之一——索引(index)。咱們知道,《高性能SQL調優精要與案例解析》一書中也再三強調索引對SQL調優的重要性,但是上篇文章中也談到,只看案例和解決問題的具體方法,而不掌握SQL調優的基礎知識,是沒有用的,咱們必須作到知其然,更要知其因此然,才能作到融會貫通,活學活用,進而將SQL調優技術掌握到爐火純青的地步。因《高性能SQL調優精要與案例解析》主要以Oracle數據庫爲基礎,對SQL調優技術進行了講解,上篇文章中,我也說到,各關係庫就SQL調優的分析和解決問題的思路、方法和步驟來講,幾乎徹底同樣,只是具體命令、方法和形式有所差異而已。那麼據此,咱們今天就對各主流關係庫的索引機制進行簡要闡述,以幫助讀者能更加深刻理解和掌握《高性能SQL調優精要與案例解析》一書中的內容和精髓,更寄但願能使其餘同窗多多受益。但關係庫中,索引類型不止一種,而不一樣關係庫,相同關係庫不一樣版本之間,也有差異,那麼,下面,咱們僅就應用最普遍的B*tree索引加以介紹。sql

一、Oracle B*tree索引:Oracle中B*Tree索引的組織結構圖在《高性能SQL調優精要與案例解析》一書中均有詳細描述,這裏再也不贅述,須要強調的是,Oracle中B*Tree的非葉級塊(non-leaf level block )中,存儲的只有索引列的鍵值(單列索引的列值或多列索引的列值組合)最大值和指向下一級葉級塊(leaf level block)或非葉級塊的指針(pointer),這裏的指針,也就是塊的文件號+塊號。而Oracle中B*Tree的葉級塊中,則存儲了索引列的鍵值+ROWID(數據行所在文件號+塊號+槽號)這樣,經過B*Tree中的鍵值和ROWID值,就能很容易的經過索引查找到表中的數據行。而Oracle中表對應的段中數據行,則是堆結構(heap),具體見《高性能SQL調優精要與案例解析》。而值得一提的是,Oracle中還有一種特殊的表組織結構,那就是索引組織表(IOT),該類表雖然在Oracle中應用很少,但在其餘關係庫中,確應用很廣,只不過名稱和細節不一樣而已,具體繼續看下面的內容。數據庫

二、MYSQL B*Tree索引:你們知道,MYSQL數據庫是一種插件數據庫,也就是其中的數據存儲引擎能夠方便的進行插拔,所以,MYSQL中也有多種存儲引擎同時存在。由於本文不是專門講述MYSQL存儲引擎的,所以,咱們就拿應用最廣的INNODB爲例來進行說明。INNODB中的B*Tree索引(MYSQL中又稱爲key),和Oracle中不一樣的是,根據具體的組織結構,又可分爲簇索引(clustered index或primary key index)和非簇索引(secondary index),在innodb中建立一個表時,系統會爲表的主鍵建立一個簇索引,若是不指定一個主鍵,系統會選定一個惟一非空索引做爲主鍵,若是不存在惟一非空索引,系統也會自動建立一個隱式主鍵,總之,表的主鍵非有不可。INNODB中表的數據,都存儲在表的簇索引中,具體說,簇索引是一個B*Tree結構,只是葉級頁(leaf level page)內除了簇索引的鍵值外,還包含了表中全部的數據列值,所以,INNODB表的數據是有序的。而INNODB表中非簇索引,其葉級塊中並不包含數據行的物理地址(相似Oracle中數據行的ROWID),而是包含了表上簇索引中的鍵值,所以,INNODB中,經過非簇索引查找數據,通常要經歷兩次鍵值查找,第一次在非簇索引上,找到簇索引的鍵值後,再到簇索引上再次查找,才能找到真正要查找的數據行。這裏強調的是,INNODB中表的簇索引並非個可選項。其組織結構和Oracle中的索引組織表相似。mvc

3.SQL SERVER B*Tree索引:SQL SERVER數據庫,做爲微軟的拳頭產品之一,有時也被人們俗稱爲MSSQL,目前國內外市場有着至關的佔有率。MSSQL中的B*Tree索引,和MYSQL中的相似,也分爲簇索引(clustered index)和非簇索引(nonclustered index),但和MYSQL中B*Tree索引不一樣的是,MSSQL中表上的簇索引並不是是強制的,也就是,你建立一張表,該表是一張堆表,也就是其對應的段是以堆的形式組織和存儲的,堆的概念,《高性能SQL調優精要與案例解析》一書中有詳細論述,這裏再也不贅述。MSSQL中的堆表上,若是你建立了一個簇索引,那麼,該表中的數據都被移到該簇索引的葉級頁(leaf level page)中,而且以該簇索引的鍵值順序排序組織和存儲,原來的堆再也不存在,若是你選擇在該表上不建立簇索引,那麼,該表就會一直以堆的形式存在。而MSSQL中的非簇索引,由於簇索引的存在與否,其內部組織和機制也分兩種狀況,當表上存在簇索引時,非簇索引的葉級頁中存儲的是簇索引的鍵值,也就是不存在指向相關數據行物理地址的指針;而若是表上不存在簇索引時,非簇索引葉級頁中就會存儲指向表中相關數據行物理地址的指針(這個指針MSSQL中叫作rid)。而無論表上是否存在簇索引,MSSQL將經過非簇索引查找數據行的行爲稱爲書籤查找(bookmark lookup),雖然,MSSQL中,通常將主鍵做爲表上的簇索引來進行使用和建立。咱們能夠看到,MSSQL中的簇索引,在組織結構上和Oracle中的索引組織表及MYSQL中的簇索引類似。post

4.Postgresql B*Tree索引:Postgresql數據庫,做爲最強大的開源關係庫之一,號稱免費版的Oracle,但就其應用特色、行鎖及MVCC等方面具體內部實現來說,確實與Oracle有不少類似之處,也能夠說是關係庫你們族中,和Oracle最相近的一款關係庫。上面咱們也說到,Postgresql數據庫在不少方面和Oracle很是類似,那麼,B*Tree索引的組織結構和應用也不例外,Postgresql數據庫中的B*Tree索引和Oracle中很類似,也並無MYSQL和MSSQL數據庫中簇索引一說。值得一提的是,Postgresql中的表和索引等數據庫對象,都是以單獨的文件形式組織和存儲,8k大小的數據頁也與Oracle中的塊不一樣,Postgresql中的mvcc與Oracle中的實現機制也有很大區別,由於,Postgresql表中數據的前影像數據和當前版本存儲在一塊兒,須要按期經過vaccum進行清除。更值得一提的是,由於Postgresql中B*Tree索引中並不存在數據的版本信息,所以,SQL語句的索引覆蓋技術並不存在,不管索引列是否能覆蓋SQL語句的全部列,都須要回表操做來確認具體數據行的版本信息,雖然,在postgresql9.2版本中引進了scan-only scans操做,這雖然在有些時候能夠避開回表操做,但須要訪問表的VM文件,更關鍵的是,若是VM文件中的相應位(bit)爲unset狀態,仍是須要回表,所以,鑑於其機制上的侷限,該技術實際中價值並沒那麼大,也許對寫少讀多的業務,會有必定的價值。性能

以上,僅就經常使用主流關係庫索引機制作簡要陳述,以幫助各位讀者理解《高性能SQL調優精要及案例解析》一書內容,同時,也但願其餘同窗多多受益。優化

相關文章
相關標籤/搜索