1. InnoDB快速索引建立數據庫
InnoDB快速索引建立,即在表中已經存在大量數據的狀況下,可以快速建立和刪除輔助索引的能力。服務器
1.1 背景併發
對於老版本的MySQL,在InnoDB表中已經存在數據的狀況下,對其添加或刪除索引的過程十分緩慢,那時create index和drop index語句的工做方式爲:性能
① 建立一個空的且帶有目標索引結構的新表;spa
② 逐行拷貝數據行到新表,插入新行的同時更新索引;排序
③ 所有拷貝完後,刪除舊錶,並將新表重命名爲舊錶名字;索引
1.2 版本要求事務
從MySQL 5.5開始,爲InnoDB表建立和刪除輔助索引再也不須要複製整個表的內容,從而使得操做速度大爲提高。內存
1.3 適用範圍table
快速索引建立的性能加速適用於輔助索引,不適用於主鍵索引。InnoDB表中的數據行存儲在基於主鍵組織的聚簇索引中,造成某些數據庫系統稱爲的「索引組織表」。由於表結構與主鍵緊密相關,所以重定義主鍵索引老是須要複製表中的數據。
1.3 方法技巧
這種新機制一般也意味着,你可使用以下方法加速索引表的建立和加載:先建立只有聚簇索引的表,而後加載數據,最後再添加輔助索引
1.4 語法
InnoDB快速索引建立的語法仍舊是create index, drop index, alter table
◇ alter table
你能夠在一條alter table語句中爲一個表同時建立多個索引,並且因爲只須要掃描一次聚簇索引,因此這種作法的效率也更高。例如:
alter table tbl_name add index (B), add unique index (C);
若是在alter table語句以前已經有大量的數據行被插入到表中,那麼先插入數據後添加輔助索引將比先添加輔助索引後加載數據要快得多
◇ crate index
你也能夠一次建立一個索引,但此時每條create index語句都須要掃描一次聚簇索引,所以效率上不如上面的alter table,例如:
create index B on tbl_name (B);
create unique index C on tbl_name (C);
◇ drop index
刪除InnoDB表的輔助索引一樣也不須要複製表中的數據,你能夠在一條alter table語句中同時刪除多個索引,或者使用多個drop index語句。例如:
alter table tbl_name drop index B, drop index C;
或者
drop index B on tbl_name;
drop index C on tbl_name;
1.5 實現細節
☆ InnoDB有兩種類型的索引:聚簇索引和輔助索引。由於聚簇索引把數據值存儲在B-tree節點裏面,因此添加或刪除聚簇索引老是會引起數據複製,並建立表的新副本。同時由於每一個輔助索引都包含了主鍵值的副本,因此當你修改主鍵時,所有輔助索引都須要從新建立;
☆ 刪除輔助索引很簡單。服務器只須要更新內部的InnoDB系統表和MySQL數據字典表,以反映索引再也不存在的事實便可。同時InnoDB會把該索引佔用的空間返還給索引所在的表空間,以便新索引或其它表的數據行可使用;
☆ 添加輔助索引時,InnoDB會對錶進行掃描,並使用內存緩衝區和臨時文件按輔助索引列的列值對數據行進行排序。而後B-tree就以鍵值序被建立,這比以隨機順序把行插入索引更有效。因爲B樹節點被填滿後自動分裂,因此以這種方式構建索引會致使索引具備更高的填充因子,從而使後續訪問更高效;
1.6 併發問題
☆ 建立輔助索引
① 建立或刪除InnoDB輔助索引時,表被鎖定在共享模式下。此時,任何寫操做都將被阻塞,但讀操做不受影響;
② 建立InnoDB輔助索引的create index和alter table語句開始執行後,對該表能夠查詢,但不能更新;
☆ 修改聚簇索引
① 更改表的聚簇索引時,因爲必須複製數據,因此表將以獨佔模式被鎖定。所以,在建立新的聚簇索引期間,表上的全部操做都將被阻塞;
② 修改InnoDB聚簇索引的alter table語句開始執行後,全部的查詢也必須等待,直到操做完成;
③ 修改主鍵的alter table語句開始執行後,任何事務都不能夠訪問該表,由於在聚簇索引重構期間老表已經被刪除;
☆ 語句執行
① 對於InnoDB表,create index和alter table語句老是會等待當前正在訪問表的事物提交或回滾;
② 重定義InnoDB主鍵的alter table操做會等待當前正在訪問該表的全部select語句執行完,或是等待其所在的事物提交;
☆ 內容
新建立的輔助索引只包括create index和alter table語句開始執行時表中已提交的數據,而不包括未提交數據、老版本數據(MVCC)和已標記爲刪除但還未刪除的數據
1.7 重建聚簇索引的過程
MySQL建立新的聚簇索引的過程爲:建立一個具備目標索引結構的臨時表,而後從原表向臨時表複製數據。一旦數據複製完成,原表被重命名爲一個其它的臨時名字,而臨時表被賦予原表的名字,最後一步是從數據庫刪除原表。
重建InnoDB聚簇索引須要將數據拷貝到一個全新的聚簇索引。請注意,全部的InnoDB表都以聚簇索引形式存儲。
1.8 崩潰恢復
在alter table語句執行期間,若是服務器崩潰,沒有數據會丟失。可是聚簇索引和輔助索引的崩潰恢復過程是不一樣的:
① 若是在建立InnoDB輔助索引時服務器崩潰,則在恢復時,MySQL將刪除任何部分建立的索引。你必須從新運行alter table或create index語句;
② InnoDB聚簇索引的崩潰恢復較爲複雜,請聯繫MySQL支持;
1.9 侷限性
① 同時包含了drop index和add index,且二者指定的是同一個索引的alter table語句,使用的是表複製,而不是快速索引建立;
② 臨時表的索引建立使用的是表複製,而不是快速索引建立;
③ 爲避免InnoDB數據字典和MySQL數據字典之間的一致性問題,當使用alter table ... change語法重命名列時,使用的是表複製而不是快速索引建立;
④ MySQL 5.5不支持高效地建立或刪除外鍵約束。所以,若是使用alter table添加或刪除references約束,子表將被複制,而不是使用快速索引建立;
⑤ InnoDB表的optimize table被自動映射爲alter table操做,以重建表、更新索引統計信息,並釋放聚簇索引中未使用的空間。此操做沒法使用快速索引建立。同時,輔助索引也沒法被高效地建立,由於輔助索引的鍵是根據它們在主鍵中出現的順序插入的。