1. 程式人生 > >mysql儲存引擎中索引的實現機制

mysql儲存引擎中索引的實現機制

一、儲存引擎 MySQL中的資料用各種不同的技術儲存在檔案中,這些技術中的每一種技術都使用不同的儲存機制、索引技巧、鎖定水平並且最終提供廣泛的不同的功能和能力。這些不同的技術以及配套的相關功能在 MySQL中被稱作儲存引擎(也稱作表型別)。

我的理解是,資料儲存使用不同的資料結構,使得它們各自支援不同的技術和功能,因此劃分成不同的儲存引擎。而儲存引擎是對應表的,所以也被稱為表型別。

用以下指令可以檢視MySQL中支援的儲存引擎,挑幾個整理一下知識。

show engines;

+——————–+———+————————————————  —————-+————–+——+————+  | Engine | Support | Comment  | Transactions | XA | Savepoints |  +——————–+———+————————————————  —————-+————–+——+————+  | MRG_MYISAM | YES | Collection of identical MyISAM tables  | NO | NO | NO |  | CSV | YES | CSV storage engine  | NO | NO | NO |  | MyISAM | YES | MyISAM storage engine  | NO | NO | NO |  | BLACKHOLE | YES | /dev/null storage engine (anything you write to  it disappears) | NO | NO | NO |  | MEMORY | YES | Hash based, stored in memory, useful for tempor  ary tables | NO | NO | NO |  | FEDERATED | NO | Federated MySQL storage engine  | NULL | NULL | NULL |  | ARCHIVE | YES | Archive storage engine  | NO | NO | NO |  | InnoDB | DEFAULT | Supports transactions, row-level locking, and f  oreign keys | YES | YES | YES |  | PERFORMANCE_SCHEMA | YES | Performance Schema  | NO | NO | NO |  +——————–+———+————————————————  —————-+————–+——+————+  9 rows in set (0.00 sec)

support一列代表是否支援該儲存引擎,yes表示支援、no表示不支援、default表示預設使用、disabled代表被關閉;transactions一列代表是否支援事務處理;xa表示是否支援分散式事務,savepoints表示是否支援分散式事務。

1.InnoDB(MySQL預設儲存引擎 從版本5.5.5開始) 支援事務,行級鎖,以及外來鍵,擁有高併發處理能力。但是在建立索引和載入資料時,比MyISAM慢。

2.MyISAM 不支援事務和行級鎖。所以速度很快,效能優秀。可以對整張表加鎖,支援併發插入,支援全文索引。

3.MEMORY 支援Hash索引,記憶體表,Memory引擎將資料儲存在記憶體中,表結構不是儲存在記憶體中的,查詢時不需要執行磁碟I/O操作,所以要比MyISAM和InnoDB快很多倍,但是資料庫斷電或是重啟後,表中的資料將會丟失,表結構不會丟失。

InnoDB跟MyISAM的區別 1.儲存結構  MyISAM:每個MyISAM在磁碟上儲存成三個檔案。第一個檔案的名字以表的名字開始,副檔名指出檔案型別。.frm檔案儲存表定義。資料檔案的副檔名為.MYD (MYData)。索引檔案的副檔名是.MYI (MYIndex)。  InnoDB:所有的表都儲存在同一個資料檔案中(也可能是多個檔案,或者是獨立的表空間檔案),InnoDB表的大小隻受限於作業系統檔案的大小,一般為2GB。 2.儲存空間  MyISAM:可被壓縮,儲存空間較小。支援三種不同的儲存格式:靜態表(預設,但是注意資料末尾不能有空格,會被去掉)、動態表、壓縮表。  InnoDB:需要更多的記憶體和儲存,它會在主記憶體中建立其專用的緩衝池用於高速緩衝資料和索引。 3.可移植性、備份及恢復  MyISAM:資料是以檔案的形式儲存,所以在跨平臺的資料轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。  InnoDB:免費的方案可以是拷貝資料檔案、備份 binlog,或者用 mysqldump,在資料量達到幾十G的時候就相對痛苦了。 4.事務支援  MyISAM:強調的是效能,每次查詢具有原子性,其執行速度比InnoDB型別更快,但是不提供事務支援。  InnoDB:提供事務支援事務,外部鍵等高階資料庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。 5.AUTO_INCREMENT  MyISAM:可以和其他欄位一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據前面幾列進行排序後遞增。  InnoDB:InnoDB中必須包含只有該欄位的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。 6.表鎖差異  MyISAM:只支援表級鎖,使用者在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的資料。  InnoDB:支援事務和行級鎖,是innodb的最大特色。行鎖大幅度提高了多使用者併發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。 7.全文索引  MyISAM:支援 FULLTEXT型別的全文索引  InnoDB:不支援FULLTEXT型別的全文索引,但是innodb可以使用sphinx外掛支援全文索引,並且效果更好。 8.表主鍵  MyISAM:允許沒有任何索引和主鍵的表存在,索引都是儲存行的地址。  InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6位元組的主鍵(使用者不可見),資料是主索引的一部分,附加索引儲存的是主索引的值。 9.表的具體行數  MyISAM:儲存有表的總行數,如果select count(*) from table;會直接取出出該值。  InnoDB:沒有儲存表的總行數,如果使用select count(*) from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件後,myisam和innodb處理的方式都一樣。 10.CURD操作  MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。  InnoDB:如果你的資料執行大量的INSERT或UPDATE,出於效能方面的考慮,應該使用InnoDB表。DELETE 從效能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空儲存有大量資料的表,最好使用truncate table這個命令。 11.外來鍵  MyISAM:不支援  InnoDB:支援 二、索引的資料結構 索引是一種資料結構。索引本身很大,不可能全部儲存在記憶體中,因此索引以索引表的形式儲存在磁碟中。

1.B+樹索引 並不能找到一個給定健值的具體行,B+樹索引只能找到被查詢資料行所在的頁,然後從資料庫將頁讀入記憶體,在記憶體中查詢。  B+樹索引可以分為聚集索引和輔助索引。聚簇索引是按照資料存放的邏輯地址為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對於單行的檢索很快。

聚集索引  聚集索引是一種索引組織形式,索引的鍵值邏輯順序決定了表資料行的物理儲存順序。  聚集索引對於那些經常要搜尋範圍值的列特別有效。使用聚集索引找到包含第一個值的行後,便可以確保包含後續索引值的行在物理相鄰。  InnoDB的資料檔案本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識資料記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含欄位作為主鍵,這個欄位長度為6個位元組,型別為長整形。  輔助索引中,葉結點的data域存放的是對應記錄的主鍵的key。  對於建立輔助索引的表需要先根據輔助索引找到相應的主鍵,再根據主鍵在聚集索引中找到相應的記錄集。

非聚集索引  非聚集索引則就是普通索引了,僅僅只是對資料列建立相應的索引,不影響整個表的物理儲存順序。  主鍵索引中,葉節點的data域存放的是資料記錄的地址,如果指定的Key存在,則取出其data域的值,然後以data域的值為地址,讀取相應資料記錄。(MYISAM採用此種索引方式)。

區別

聚集索引表裡資料物理儲存順序和主鍵索引的順序一致,所以如果新增資料是離散的,會導致資料塊趨於離散,而不是趨於順序。而非聚集索引表資料寫入的順序是按寫入時間順序儲存的。 聚簇索引索引的葉節點就是資料節點;而非聚簇索引的葉節點仍然是索引節點,只不過有一個指標指向對應的資料塊。 適用情景

2.Hash索引 在《資料庫索引探索》中已經整理過Hash索引的知識,這裡不再重複。

三、MySQL中的索引使用 1.普通索引 最普通的索引,沒有任何限制。

# 建立表的同時建立索引 CREATE TABLE `artical` (     `id` int(11) NOT NULL AUTO_INCREMENT,     `subject` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,     `time` Date NULL DEFAULT NULL,     PRIMARY KEY(`id`),     INDEX index_subject (subject) );

# 直接建立索引 CREATE INDEX <index_name> ON <table_name>(<column_name>);

# 修改表結構的方式新增索引 ALTER TABLE <table_name> ADD INDEX index_name (<column_name>); 實際上,最好的做法是建立表的時候建立索引,如果建立表之後再修改新建索引的話,對於聚集索引,會根據原來的表,建立一個新的錶帶有索引資料結構,再把原來的表刪去,新建立的表改成原來的表的名字。而非聚集索引則是通過修改索引檔案來完成。所以都是需要佔用額外的資源來修改或新建索引的。

2.唯一索引 與普通索引的不同的是,索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。

# 建立表的時候直接指定 CREATE TABLE `user` (     `id` int(11) NOT NULL AUTO_INCREMENT,     `name` char(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     `tel` char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     PRIMARY KEY(`id`),     UNIQUE index_subject (name) );

# 直接建立索引 CREATE UNIQUE INDEX <index_name> ON <table_name>(<column_name>);

# 修改表結構的方式新增索引 ALTER TABLE <table_name> ADD UNIQUE index_name (<column_name>); 3.主鍵索引 索引值必須唯一,不能為NULL,在B+TREE中的InnoDB引擎中,主鍵索引起到了至關重要的地位。

4.全文索引 MySQL從3.23.23版開始支援全文索引和全文檢索,FULLTEXT索引僅可用於 MyISAM 表;他們可以從CHAR、VARCHAR或TEXT列中作為CREATE TABLE語句的一部分被建立,或是隨後使用ALTER TABLE 或CREATE INDEX被新增。

# 建立表的時候新增全文索引 CREATE TABLE `artical` (     `id` int(11) NOT NULL AUTO_INCREMENT,     `subject` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,     `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,     `time` Date NULL DEFAULT NULL,     PRIMARY KEY(`id`),     FULLTEXT (content) )engine=MyISAM;

# 修改表結構新增全文索引 ALTER TABLE artical ADD FULLTEXT INDEX index_content(content);

# 直接建立索引 CREATE FULLTEXT INDEX index_content ON artical(content); 5.單列索引,多列索引 多個單列索引與單個多列索引的查詢效果不同,因為執行查詢時,MySQL只能使用一個索引,會從多個索引中選擇一個限制最為嚴格的索引。

6.組合索引 平時用的SQL查詢語句一般都有比較多的限制條件,所以為了進一步榨取MySQL的效率,就要考慮建立組合索引。例如上表中針對title和time建立一個組合索引:ALTER TABLE article ADD INDEX index_titme_time (subject,title(50),time(10)),實際上包含三個索引(subject),(subject, title), (subject, title, time)。

在使用查詢的時候遵循“最左字首”:

不按索引最左列開始查詢不適用索引。例如對idnex(c1,c2,c3),使用where c2 = “aaa” and c3 = “bbb”不能使用索引 查詢中某個列有範圍查詢,則其右邊的所有列都無法使用查詢。例如對idnex(c1,c2,c3),where c1 = “xxx” and c2 like = “aa%” and c3 = “sss”查詢只會使用索引的前兩列,因為like是範圍查詢 不能跳過某個欄位進行查詢。 四、使用索引的優點和缺點 優點 1.可以通過建立唯一索引或者主鍵索引,保證資料庫表中每一行資料的唯一性 2.建立索引可以大大提高檢索的資料,以及減少表的檢索行數 3.在表連線的連線條件,可以加速表與表直接的相連 4.在分組和排序字句進行資料檢索,可以減少查詢時間中分組和 排序時所消耗的時間(資料庫的記錄會重新排序) 5.建立索引,在查詢中使用索引,可以提高效能 缺點 1.建立索引和維護索引會耗費時間,隨著資料量的增加而增加 2.索引檔案會佔用物理空間,除了資料表需要佔用物理空間之外,每一個索引還會佔用一定的物理空間 3.當對錶的資料進行 INSERT,UPDATE,DELETE 的時候,索引也要動態的維護,這樣就會降低資料的維護速度,(建立索引會佔用磁碟空間的索引檔案。一般情況這個問題不太嚴重,但如果你在一個大表上建立了多種組合索引,索引檔案的會膨脹很快)。