1. 程式人生 > >MySql索引原理及使用

MySql索引原理及使用

索引用於快速查找出在某個列中有一特定值的行,不適用索引,MySQL必須從第一條記錄開始讀完整個表,直到找到相關行。表越大,查詢資料花費的時間越多。如果表中查詢的列有一個索引,MySQL能快速達到某個位置去搜索檔案,而不必檢視所有資料。因此使用索引是資料庫優化最直接有效的方式,所以瞭解索引對於開發人員尤為重要。

索引簡介

索引是一個單獨的、儲存在磁碟上的資料庫結構,他們包含著對資料表裡所有記錄的引用指標。使用索引用於快速找出在某個或者多個列中有一特定值的行,所有MySQL列型別都可以被索引,對於相關列使用索引是提高查詢操作速度的最佳途徑。

索引的優點:

1.通過建立唯一索引,可以保證資料庫表中每一行資料的唯一性。

2.可以大大加快資料的查詢速度,這也是建立索引的最主要原因。

3.在實現資料的參考完整性方面,可以加速表與表之間的連線。

4.在使用分組和排序字句進行資料查詢時,也可以顯著減少查詢中分組和排序的時間。

索引的缺點:

1.建立和維護索引要耗費時間,資料量越大耗費時間也會越長。

2.索引需要佔磁碟空間,除了資料表佔資料空間外,每一個索引還要佔一定的物理空間,如果有大量的索引,索引檔案可能比資料檔案更快達到最大檔案尺寸。

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

索引的原理

一 索引原理
索引的目的在於提高查詢效率,與我們查閱圖書所用的目錄是一個道理:先定位到章,然後定位到該章下的一個小節,然後找到頁數。相似的例子還有:查字典,查火車車次,飛機航班等

本質都是:通過不斷地縮小想要獲取資料的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,我們可以總是用同一種查詢方式來鎖定資料。

資料庫也是一樣,但顯然要複雜的多,因為不僅面臨著等值查詢,還有範圍查詢(>、<、between、in)、模糊查詢(like)、並集查詢(or)等等。資料庫應該選擇怎麼樣的方式來應對所有的問題呢?我們回想字典的例子,能不能把資料分成段,然後分段查詢呢?最簡單的如果1000條資料,1到100分成第一段,101到200分成第二段,201到300分成第三段......這樣查第250條資料,只要找第三段就可以了,一下子去除了90%的無效資料。但如果是1千萬的記錄呢,分成幾段比較好?稍有演算法基礎的同學會想到搜尋樹,其平均複雜度是lgN,具有不錯的查詢效能。但這裡我們忽略了一個關鍵的問題,複雜度模型是基於每次相同的操作成本來考慮的。而資料庫實現比較複雜,一方面資料是儲存在磁碟上的,另外一方面為了提高效能,每次又可以把部分資料讀入記憶體來計算,因為我們知道訪問磁碟的成本大概是訪問記憶體的十萬倍左右,所以簡單的搜尋樹難以滿足複雜的應用場景。

 二 磁碟IO與預讀

考慮到磁碟IO是非常高昂的操作,計算機作業系統做了一些優化,當一次IO時,不光把當前磁碟地址的資料,而是把相鄰的資料也都讀取到記憶體緩衝區內,因為區域性預讀性原理告訴我們,當計算機訪問一個地址的資料的時候,與其相鄰的資料也會很快被訪問到。每一次IO讀取的資料我們稱之為一頁(page)。具體一頁有多大資料跟作業系統有關,一般為4k或8k,也就是我們讀取一頁內的資料時候,實際上才發生了一次IO,這個理論對於索引的資料結構設計非常有幫助。

三、索引的資料結構
任何一種資料結構都不是憑空產生的,一定會有它的背景和使用場景,我們現在總結一下,我們需要這種資料結構能夠做些什麼,其實很簡單,那就是:每次查詢資料時把磁碟IO次數控制在一個很小的數量級,最好是常數數量級。那麼我們就想到如果一個高度可控的多路搜尋樹是否能滿足需求呢?就這樣,b+樹應運而生。

如上圖,是一顆b+樹,關於b+樹的定義可以參見B+樹,這裡只說一些重點,淺藍色的塊我們稱之為一個磁碟塊,可以看到每個磁碟塊包含幾個資料項(深藍色所示)和指標(黃色所示),如磁碟塊1包含資料項17和35,包含指標P1、P2、P3,P1表示小於17的磁碟塊,P2表示在17和35之間的磁碟塊,P3表示大於35的磁碟塊。真實的資料存在於葉子節點即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非葉子節點只不儲存真實的資料,只儲存指引搜尋方向的資料項,如17、35並不真實存在於資料表中。

###b+樹的查詢過程

如圖所示,如果要查詢資料項29,那麼首先會把磁碟塊1由磁碟載入到記憶體,此時發生一次IO,在記憶體中用二分查詢確定29在17和35之間,鎖定磁碟塊1的P2指標,記憶體時間因為非常短(相比磁碟的IO)可以忽略不計,通過磁碟塊1的P2指標的磁碟地址把磁碟塊3由磁碟載入到記憶體,發生第二次IO,29在26和30之間,鎖定磁碟塊3的P2指標,通過指標載入磁碟塊8到記憶體,發生第三次IO,同時記憶體中做二分查詢找到29,結束查詢,總計三次IO。真實的情況是,3層的b+樹可以表示上百萬的資料,如果上百萬的資料查詢只需要三次IO,效能提高將是巨大的,如果沒有索引,每個資料項都要發生一次IO,那麼總共需要百萬次的IO,顯然成本非常非常高。

###b+樹性質
1.索引欄位要儘量的小:通過上面的分析,我們知道IO次數取決於b+數的高度h,假設當前資料表的資料為N,每個磁碟塊的資料項的數量是m,則有h=㏒(m+1)N,當資料量N一定的情況下,m越大,h越小;而m = 磁碟塊的大小 / 資料項的大小,磁碟塊的大小也就是一個數據頁的大小,是固定的,如果資料項佔的空間越小,資料項的數量越多,樹的高度越低。這就是為什麼每個資料項,即索引欄位要儘量的小,比如int佔4位元組,要比bigint8位元組少一半。這也是為什麼b+樹要求把真實的資料放到葉子節點而不是內層節點,一旦放到內層節點,磁碟塊的資料項會大幅度下降,導致樹增高。當資料項等於1時將會退化成線性表。

索引的分類

索引是在儲存引擎中實現的,因此,每種儲存引擎的索引都不一定完全相同,並且每種儲存引擎也不一定支援所有索引型別。根據儲存引擎定義每個表的最大索引數和最大索引長度。所有的儲存引擎支援每個表至少16個索引,總長度至少為256位元組,大多數儲存引擎有更高的限制。MySQL中索引的儲存型別有兩種:Btree和hash,具體和表的儲存引擎相關;MyISAM和InnoDB儲存引擎只支援Btree索引,MEMORY/HEAP儲存引擎可以支援hash和Btree索引。

MySQL索引的分類:

1.普通索引:MySQL的基本索引型別,允許索引欄位的列插入重複值和空值。

2.唯一索引:索引列欄位必須唯一,但允許有空值,如果是組合索引,則組合必須唯一,主鍵索引是一種特殊的唯一索引,不允許有空值。

3.單列索引和組合索引:單列索引只包含單個列,一個表可以有多個單列索引。組合索引指在表的多個欄位組合上建立索引,使用組合索引時遵循最左字首集合。

4.全文索引:全文索引型別為FullText,在定義索引的列上支援值得全文查詢,允許在這些索引列中插入重複值和空置,全文索引可以在char、varchar和text型別的列上建立,MySQL中只有MyISAM儲存引擎支援全文索引。

5.空間索引:空間索引是對空間資料型別的欄位建立的索引,只能在MyISAM儲存引擎的表中建立。

索引建立

建立表的時候建立索引

語法結構:

CREATE TABLE table_name [col_name data_type]

[UNIQUE | FULLTEXT | SPATITAL] [INDEX | KEY] [index_name] (col_name [length]) [ASC | DESC]

1.建立普通索引

最基本的索引型別,沒有唯一性之類的限制,其作用只是加快對資料庫的訪問速度。

CREATE TABLE book
(
book_id                        INT NOT NULL,
book_name                      VARCHAR(255) NOT NULL,
info                           VARCHAR(255) NOT NULL,
INDEX(info)
);

沒有指定索引名稱時會預設使用索引欄位作為索引名稱,此處為給欄位info建立名稱為info索引。

2.建立唯一索引

建立唯一索引的主要原因是減少查詢索引列操作的執行時間,尤其是對比較龐大的資料表,它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。

CREATE TABLE t1
(
id                        INT NOT NULL,
name                      CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
); 

此處為給id欄位建立一個名為UniqIdx的唯一索引。

3.建立單列索引

單列索引是在資料表中某一個欄位上建立的索引,一個表中可以建立多個單列索引,前面兩個例子建立的都為單列索引

CREATE TABLE t2
(
id                        INT NOT NULL,
name                      CHAR(30) NULL,
INDEX SingleIdx(name(20))
); 
此處為給name欄位建立一個名為SingleIdx的單列索引,索引長度為20。

4.建立組合索引

組合索引是在多個欄位上建立一個索引

CREATE TABLE t3
(
id                        INT NOT NULL,
name                      CHAR(30) NOT NULL,
age                       INT NOT NULL,                      
info                      VARCHAR(255),
INDEX MultiIdx(id, name, age(100))
);

此處為給id,name和age欄位建立一個名為MultiIdx的組合索引。

組合索引可起幾個索引的作用,但必須遵從“最左字首”:利用索引中最左邊的列集來匹配行。例如這裡又id,name和age 3個欄位構成的索引,索引行中按id/name/age的順序存放,索引可以搜尋下面欄位組合:(id,name,age)、(id,name) 或者 id。如果列不構成索引最左面的字首,MySQL不能使用區域性索引,如(age)或者(name,age)組合則不能使用索引查詢。

5.建立全文索引

FullText(全文索引)可以用於全文搜尋。只有MyISAM儲存引擎支援FullText索引,並且只為CHAR、VARCHAR和TEXT列建立索引。索引總是對整個列進行,不支援區域性(字首)索引。

CREATE TABLE t4
(
id                        INT NOT NULL,
name                      CHAR(30) NOT NULL,
age                       INT NOT NULL,                      
info                      VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
) ENGINE=MyISAM;

此處為給info欄位建立一個名為FullTxtIdx的組合索引,索引長度為20,全文索引非常適合於大型資料集,對於小的資料集,它的用處比較小。

6.建立空間索引

空間索引必須在MyISAM型別的表中建立,且空間型別的欄位必須為非空。

CREATE TABLE t5
(
g                        GEOMETRY NOT NULL,
SPATIAL                  INDEX spatIdx(g)
) ENGINE=MyISAM;

此處為g欄位上建立了名為spatIdx的空間索引,注意建立時指定空間型別欄位值的非空約束,並且表的儲存引擎為MyISAM。

在已經存在的表上建立索引

1.使用 ALTER TABLE 語句建立索引

語法結構:

ALTER TABLE table_name ADD [UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY]

[index_name] (col_name[length],...) [ASC | DESC]

例如:使用ALTER TABLE在bookname欄位上新增名為BkNameIdx索引,SQL語句如下:

ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));

其他型別的索引只需將INDEX換成其他型別即可如:UNIQUE INDEX,FULLTEXT INDEX,SPATIAL INDEX。

2.使用 CREATE INDEX 建立索引

語法結構:

CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name

ON table_name (col_name[length],...) [ASC | DESC]

例如:使用CREATE INDEX在bookname欄位上新增名為BkNameIdx索引,SQL語句如下:

CREATE INDEX BkNameIdx ON book(bookname)
其他型別的索引只需將INDEX換成其他型別即可如:UNIQUE INDEX,FULLTEXT INDEX,SPATIAL INDEX。

刪除索引

1.使用ALTER TABLE刪除索引

語法結構:ALTER TABLE table_name DROP INDEX index_name;

2.使用DROP INDEX語句刪除索引

語法結構:DROP INDEX index_name ON table_name;

總結

為資料庫選擇正確的索引是一項複雜的任務,如果索引列較少,則需要的磁碟空間和維護開銷都較少。如果在一個大表上建立了多種組合索引,索引檔案也會膨脹很快。另一方面,索引較多可覆蓋更多的查詢,可能需要實驗若干不同的設計,才能找到最有效的索引。對字串型別的欄位進行索引,如果可能應該指定一個字首長度。例如,如果有個CHAR(255)的列,在前10個或者30個字元內,多數值是惟一的,則不需要對整個列進行索引,短索引不僅可以提高查詢速度而且可以節省磁碟空間、減少I/O操作,因此如何更好的使用索引,還需要我們在實際中多嘗試多測驗。

相關推薦

MySQL索引原理慢查詢優化(轉)

範圍 很難 等於 right 事件 原理 插入 jpg 個人網站 轉自:美團點評技術團隊http://tech.meituan.com/mysql-index.html MySQL憑借著出色的性能、低廉的成本、豐富的資源,已經成為絕大多數互聯網公司的首選關系型數據庫。雖然性

MySQL索引原理慢查詢優化-zz

`` 原理 並不是 計劃 ora 實的 birt 總計 war https://tech.meituan.com/mysql-index.html MySQL憑借著出色的性能、低廉的成本、豐富的資源,已經成為絕大多數互聯網公司的首選關系型數據庫。雖然性能出色,但所謂“好馬配

MySQL索引原理BTree(B-/+Tree)結構詳解

  目錄 摘要 資料結構及演算法基礎 索引的本質 B-Tree和B+Tree B-Tree B+Tree 帶有順序訪問指標的B+Tree 為什麼使用B-Tree(B+Tree) 主存存取原理 磁碟存取原理 區域性性原理與磁碟預讀 B

MySQL索引原理慢查詢優化--美團分享

MySQL索引原理及慢查詢優化 http://tech.meituan.com/mysql-index.html MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”,如何能夠更好的使用

MySql索引原理慢查詢優化

MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”, 如何能夠更好的使用它,已經成為開發工程師的必修課,我們經常會從職位描述上看到諸如“精通MySQL”、“SQL語句優化”、“瞭解資料庫原

MySQL索引原理慢查詢優化--美團分享轉載

MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”,如何能夠更好的使用它,已經成為開發工程師的必修課,我們經常會從職位描述上看到諸如“精通MySQL”、“SQL語句優化”、“瞭解資料庫原理”等

MySql索引原理使用

索引用於快速查找出在某個列中有一特定值的行,不適用索引,MySQL必須從第一條記錄開始讀完整個表,直到找到相關行。表越大,查詢資料花費的時間越多。如果表中查詢的列有一個索引,MySQL能快速達到某個位置去搜索檔案,而不必檢視所有資料。因此使用索引是資料庫優化最直接有效的方式,

MySQL索引原理慢查詢優化(轉載)

MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”,如何能夠更好的使用它,已經成為開發工程師的必修課,我們經常會從職位描述上看到諸如“精通MySQL”、“SQL語句優化”、“瞭解

MySQL索引原理慢查詢優化(重要)

該文是我看過mysql索引和優化相關知識,講解最全面的一篇博文(是美團內部的一篇技術博文),現轉載分享給大家,希望大家能從中有所收穫! MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。雖然效能出色,但所謂“好馬配好鞍”,

MySQL索引原理慢查詢優化(轉自:美團tech)

輔助 nor bundle like 案例 應對 異常 線下 重要 背景 MySQL憑借著出色的性能、低廉的成本、豐富的資源,已經成為絕大多數互聯網公司的首選關系型數據庫。雖然性能出色,但所謂“好馬配好鞍”,如何能夠更好的使用它,已經成為開發工程師的必修課,我們經常會從職位

MySQL索引原理慢查詢優化,瞭解一下?

MySQL憑藉著出色的效能、低廉的成本、豐富的資源,已經成為絕大多數網際網路公司的首選關係型資料庫。 雖然效能出色,但所謂“好馬

MySQL索引原理SQL優化

目錄 索引(Index) 索引的原理 b+樹 MySQL如何使用索引 如何優化 索引雖好,不可濫用 如何驗證索引使用情況?

mysql資料庫索引原理使用注意事項

索引原理 索引出現的原因 在使用關係型資料庫的時候,我們常常聽到一個詞:“索引”,在優化資料庫的時候,我們常常聽到有人提到新增索引可以加快資料庫的查詢速度,今天我們就來談一談它的原理。 關係型資料庫之所以叫這個名字,是因為它採用了一種名為“關係”的資料結構來儲存資料,說簡單點就是

MySQL優化(三):索引原理索引優化

建立高效能索引索引是提高MySQL查詢效能的一個重要途徑,但過多的索引可能會導致過高的磁碟使用率以及過高的記憶體佔用,從而影響應用程式的整體效能。應當儘量避免事後才想起新增索引,因為事後可能需要監控大量的SQL才能定位到問題所在,而且新增索引的時間肯定是遠大於初始新增索引所需

mysql:索引原理與慢查詢優化

一個 mark index out 般的 test output 都是 records 一 介紹 二 索引的原理 三 索引的數據結構 三 MySQL索引管理 四 測試索引 五 正確使用索引 六 查詢優化神器-explain 七 慢查詢優化的基本步驟 八 慢日誌管理 九 參

mysql索引原理剖析

mage add 獲得 旋轉速度 tran 運行期 多個 pla 線性 一、索引的原理   所謂索引,即是快速定位與查找,那麽索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數(B+樹相比B樹,其非葉子節點占用更小的空間,可以有更多非葉子節點存放在再內存中,減少大量的

Mysql索引介紹常見索引的區別

掃描 varchar mysql查詢 運算 最優 慢慢 對比 非聚集索引 單個 關於MySQL索引的好處,如果正確合理設計並且使用索引的MySQL是一輛蘭博基尼的話,那麽沒有設計和使用索引的MySQL就是一個人力三輪車。對於沒有索引的表,單表查詢可能幾十萬數據就是瓶頸,而通

MySQL 索引原理相關文章

log body mysq blog ref blank mys top .net CSDN的整理: http://bbs.csdn.net/topics/392265880 引擎在磁盤中存儲順序的圖解: http://blog.csdn.net/php_lzr/a

MySQL索引管理執行計劃

索引管理MySQL索引管理及執行計劃第1章 索引介紹:索引是對數據庫表中一列或者多了的值進行排序的一種結構,使用索引可以快速訪問數據庫表中的特定信息,如果想按特定職員的姓名來查找,則與他在表中搜索所有的行相比,索引有助於更快的獲取信息索引的一個主要目的就是加快檢索表中的數據的方法,既能協助信息搜索者盡快找到符

MySQL索引原理以及查詢優化

地址 存儲引擎 想要 方式 聯合 執行 圖書 解決 範圍查詢 一、介紹 1.什麽是索引? 一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些復雜的查詢操作,因此對查詢語句的優化顯然