MySQL索引(index)專題
索引(Index)是幫助MySQL高效獲取資料的資料結構,它的存在形式是檔案。索引能夠幫助我們快速定位資料,它可以讓mysql高效執行,大大提高mysql的查詢(包括排序,分組)效率。
Mysql目前主要有以下幾種索引型別(按儲存結構劃分):FULLTEXT,HASH,BTREE,RTREE。
對應儲存引擎支援如下:
MyISAM | BTREE,FULLTEXT,RTREE |
Innodb | BTREE,RTREE |
Memory | HASH,BTREE |
NDB | BTREE,HASH,RTREE |
注:前面索引為儲存引擎預設索引。
MySQL索引在使用上一般有如下幾種種類(按使用功能劃分)
普通索引(INDEX),唯一索引(UNIQUE INDEX),主鍵索引(PRIMARY KEY),全文索引(FULLTEXT INDEX),外來鍵索引(FOREIGN KEY),組合索引。
2.1 索引的優點
大大加快資料的檢索速度,這也是建立索引的最主要的原因。
建立唯一性索引,保證資料庫表中每一行資料的唯一性。
加速表和表之間的連線,特別是在實現資料的參考完整性方面特別有意義。
在使用分組和排序子句進行資料檢索時,同樣可以顯著減少查詢中分組和排序的時間。
通過使用索引,可以在查詢的過程中使用優化隱藏器。
2.2 索引的缺點
建立索引和維護索引要耗費時間,這種時間隨著資料量的增加而增加。
當對錶中的資料進行增加、刪除和修改的時候,索引也要動態的維護,降低了資料的維護速度。
建立索引會佔用磁碟空間的索引檔案,尤其大表上建立了多種組合索引,索引檔案的會膨脹很快。
3.1 建表時建立索引
3.1.1 建立普通索引
查看錶結構CREATE TABLE index_normal ( c1 int default NULL, c2 varchar(30) default NULL, c3 date default NULL, INDEX normal (c3) ) engine=innodb;
mysql> show create table index_normal \G
*************************** 1. row ***************************
Table: index_normal
Create Table: CREATE TABLE `index_normal` (
`c1` int(11) DEFAULT NULL,
`c2` varchar(30) COLLATE utf8_bin DEFAULT NULL,
`c3` date DEFAULT NULL,
KEY `normal` (`c3`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
注:若不顯示指定normal為關鍵字,key會指定c3為關鍵字。
插入語句並檢視執行計劃
mysql> insert into index_normal values (1,'testing partitions','1995-07-17');
mysql> explain select * from index_normal where c3 = 1995-07-17 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: index_normal
type: ref
possible_keys: normal
key: normal
key_len: 4
ref: const
rows: 1
Extra: Using where
3.1.2 建立唯一索引
一個表中可以有多個唯一性索引,唯一性索引列允許空值。
CREATE TABLE index_unique (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL,
UNIQUE INDEX uniqueIDX (c1)
) engine=innodb;
查看錶結構
mysql> show create table index_unique \G
*************************** 1. row ***************************
Table: index_unique
Create Table: CREATE TABLE `index_unique` (
`c1` int(11) DEFAULT NULL,
`c2` varchar(30) COLLATE utf8_bin DEFAULT NULL,
`c3` date DEFAULT NULL,
UNIQUE KEY `uniqueIDX` (`c1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
3.1.3 建立主鍵索引
一個表中只能有一個主鍵索引,主鍵索引列不允許空值。因為一個表只可能有一個PRIMARY KEY索引,因此不需要指定索引名。
CREATE TABLE index_primary (
c1 int NOT NULL auto_increment,
c2 varchar(30) default NULL,
c3 date default NULL,
primary key (c1)
) engine=innodb auto_increment=10;
可以設定主鍵自增長auto_increment,及自增長開始點auto_increment=10查看錶結構
mysql> show create table index_primary \G
*************************** 1. row ***************************
Table: index_primary
Create Table: CREATE TABLE `index_primary` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(30) COLLATE utf8_bin DEFAULT NULL,
`c3` date DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
3.1.4 建立全文索引
MySQL只有MyISAM儲存引擎支援FULLTEXT索引,並且類型別為CHAR、TEXT、VARCHAR。
CREATE TABLE index_fulltext (
c1 int default NULL,
c2 varchar(300) default NULL,
c3 date default NULL,
FULLTEXT INDEX fulltextIDX (c2)
) engine=myisam;
查看錶結構
mysql> show CREATE TABLE index_fulltext \G
*************************** 1. row ***************************
Table: index_fulltext
Create Table: CREATE TABLE `index_fulltext` (
`c1` int(11) DEFAULT NULL,
`c2` varchar(300) COLLATE utf8_bin DEFAULT NULL,
`c3` date DEFAULT NULL,
FULLTEXT KEY `fulltextIDX` (`c2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
3.1.5 建立外來鍵索引
保持資料一致性,完整性,主要目的是控制儲存在外來鍵表中的資料。 使兩張表形成關聯,外來鍵只能引用外表中的列的值!
外來鍵語法規則
[CONSTRAINT 外來鍵名] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
該語法可以在 CREATE TABLE 和 ALTER TABLE 時使用,如果不指定CONSTRAINT symbol,MYSQL會自動生成一個名字。ON DELETE、ON UPDATE表示事件觸發限制,可設引數:
① RESTRICT(限制外表中的外來鍵改動,預設值)
② CASCADE(跟隨外來鍵改動)
③ SET NULL(設空值)
④ SET DEFAULT(設預設值)
⑤ NO ACTION(無動作,預設的)
建立外來鍵例項
CREATE TABLE index_foreign(
id int(11),
name varchar(20),
CONSTRAINT foreignKEY foreign key(id) references index_primary(c1)
on delete cascade on update cascade) engine=innodb;<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span>
查看錶結構
mysql> show create table index_foreign \G
*************************** 1. row ***************************
Table: index_foreign
Create Table: CREATE TABLE `index_foreign` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) COLLATE utf8_bin DEFAULT NULL,
KEY `foreignKEY` (`id`),
CONSTRAINT `index_foreign_ibfk_1` FOREIGN KEY (`id`) REFERENCES `index_primary` (`c1`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
注:有外來鍵約束的表必須是innodb型,因為在MySQL中只有InnoDB型別的表才支援外來鍵。
不能刪除有外來鍵約束的父表,否則會報錯:ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
MySQL只允許向當前表中加入外來鍵表(參照表)中已有的資料列。
在外來鍵關係中,欄位的資料型別必須相似。
外來鍵表中資料刪除,當前表中相關資料也會被級聯刪除,反之則不會。
3.2 已存在的表上通過ALTER TABLE建立索引
3.2.1 基本語法
ALTER TABLE table_name ADD INDEX index_name (column_name);
ALTER TABLE table_name ADD UNIQUE index_name (column_name);
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
ALTER TABLE table_name ADD FULLTEXT index_name (column_name);
ALTER TABLE table_name ADD CONSTRAINT foreignKEY FOREIGN KEY (index_column_name)
REFERENCES foreign_table_name (index_column_name) ON DELETE CASCADE ON UPDATE CASCADE ;
3.2.2 建立測試表
CREATE TABLE index_alter_normal (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=innodb;
CREATE TABLE index_alter_unique (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=innodb;
CREATE TABLE index_alter_primary (
c1 int NOT NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=innodb;
CREATE TABLE index_alter_fulltext (
c1 int default NULL,
c2 varchar(300) default NULL,
c3 date default NULL
) engine=myisam;
CREATE TABLE index_foreign(
id int(11),
name varchar(20)
)engine=innodb;
3.2.3 新增索引
ALTER TABLE index_alter_normal ADD INDEX normal (c3);
ALTER TABLE index_alter_unique ADD UNIQUE uniqueIDX (c1);
ALTER TABLE index_alter_primary ADD PRIMARY KEY (c1);
ALTER TABLE index_alter_fulltext ADD FULLTEXT fulltextIDX (c2);
ALTER TABLE index_foreign ADD CONSTRAINT foreignKEY FOREIGN KEY (id)
REFERENCES index_primary (c1) ON DELETE CASCADE ON UPDATE CASCADE ;
注:在已存在的表上新增主鍵只能通過alter table的方法,不能直接create primary key
若新增主鍵為自增主鍵,先增加主鍵,在新增自增長,最後新增增長起始點
新增主鍵為自增長,並設定從10開始自增:
mysql> Alter table index_alter_primary change c1 c1 int(11) not null auto_increment;
mysql> Alter table index_alter_primary auto_increment=10;
3.3 已存在的表上通過CREATE INDEX建立索引
主鍵及外來鍵的新增不能通過此方法,只能通過上面alter table的方法。
3.3.1 基本語法
CREATE INDEX index_name ON table_name (column_name);
CREATE UNIQUE INDEX index_name ON table_name (column_name);
CREATE FULLTEXT INDEX index_name ON table_name (column_name);
3.3.2 建立測試表
CREATE TABLE index_create_normal (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=innodb;
CREATE TABLE index_create_unique (
c1 int default NULL,
c2 varchar(30) default NULL,
c3 date default NULL
) engine=innodb;
CREATE TABLE index_create_fulltext (
c1 int default NULL,
c2 varchar(300) default NULL,
c3 date default NULL
) engine=myisam;
3.3.3 新增索引
CREATE INDEX normal ON index_create_normal (c3);
CREATE UNIQUE INDEX uniqueIDX ON index_create_unique (c1);
CREATE FULLTEXT INDEX fulltextIDX ON index_create_fulltext (c2);
mysql> show index from table_name;
mysql> show key from table_name;
例如:
mysql> show index from index_normal \G
*************************** 1. row ***************************
Table: index_normal
Non_unique: 1
Key_name: normal
Seq_in_index: 1
Column_name: c3
Collation: A
Cardinality: 2
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec)
mysql> show index from index_fulltext \G
*************************** 1. row ***************************
Table: index_fulltext
Non_unique: 1
Key_name: fulltextIDX
Seq_in_index: 1
Column_name: c2
Collation: NULL
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: FULLTEXT
Comment:
Index_comment:
1 row in set (0.00 sec)
注:其中普通索引,唯一索引,主鍵索引型別為btree,全文索引型別為fulltext5 刪除索引
刪除語法:
drop index index_name on table_name ;
alter table table_name drop index index_name ;
alter table table_name drop primary key ;
注:在前面的兩條語句中,都刪除了table_name中的索引index_name。而在最後一條語句中,只在刪除PRIMARY KEY索引中使用,因為一個表只可能有一個PRIMARY KEY索引,因此不需要指定索引名。如果主鍵為自增長,刪除主鍵前需要先改變自增長為普通欄位。
例如:
mysql> drop index uniqueIDX on index_unique;
mysql> alter table index_normal drop index ;
mysql> alter table index_fulltext drop index fulltextIDX;
mysql> alter table index_primary change c1 c1 int(11);//刪除自增長
mysql> alter table index_primary drop PRIMARY KEY;//刪除主鍵
mysql> alter table index_foreign drop FOREIGN KEY index_foreign_ibfk_1;//刪除外來鍵索引
注:刪除外來鍵語法如下:ALTER TABLE table-name DROP FOREIGN KEY key-id;
其中:key-id可通過show create table檢視,緊跟在CONSTRAINT之後的那個引數就是。
6.1 索引型別對比(按儲存結構劃分)
6.1.1 B-TREE索引
B-Tree索引加速了資料訪問。從B-Tree根開始,藉助中間節點頁的上界和下界值,可以快速搜尋到葉子頁層,最終找到含有需要找的值的葉子頁(或者確定無法找到需要的資料),找到對應的葉子頁後可以通過相應的指標直接找到資料表中對應的資料行。這樣儲存引擎不會掃描整個表得到需要的資料。同時B-Tree索引通常意味著索引中資料儲存時有序的,可以利用B-Tree索引來加速排序。
6.1.2 HASH索引
雜湊索引建立在雜湊表的基礎上,它只對使用了索引的每一列的精確查詢有用。對於每一行,儲存引擎計算出了被索引列的雜湊碼,它是一個較小的值(可能對具有相同索引值的不同行計算出的雜湊值不同)。索引中包含雜湊碼和對應指向資料行的指標。
hash索引由於其結構,所以在每次查詢的時候直接一次到位,不像b-tree那樣一點點的前進。所以hash索引的效率高於b-tree。hash表在處理較小資料量時具有無可比擬的素的優勢,所以hash索引很適合做快取(記憶體資料庫)。
6.1.3 FULLTEXT索引
FULLTEXT即為全文索引,目前只有MyISAM引擎支援。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上可以建立全文索引。值得一提的是,在資料量較大時候,現將資料放入一個沒有全域性索引的表中,然後再用CREATE INDEX建立FULLTEXT索引,要比先為一張表建立FULLTEXT然後再將資料寫入的速度快很多。
它的出現是為了解決WHERE name LIKE “%word%"這類針對文字的模糊查詢效率較低的問題。在沒有全文索引之前,這樣一個查詢語句是要進行遍歷資料表操作的,可見,在資料量較大時是極其的耗時的。
6.1.4 R-TREE索引
RTREE在mysql很少使用,僅支援geometry資料型別,支援該型別的儲存引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。
相對於BTREE,RTREE的優勢在於範圍查詢。
6.2 索引型別對比(按使用功能劃分)
6.2.1 普通索引
這是最基本的索引型別,而且它沒有唯一性之類的限制。
6.2.2 唯一索引
索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。
6.2.3 主鍵索引
主鍵是一種唯一性索引,但它必須指定為“PRIMARY KEY”,且不允許有空值。如果你曾經用過AUTO_INCREMENT型別的列,你可能已經熟悉主鍵之類的概念了。主鍵一般在建立表的時候指定,例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ”。但是,我們也可以通過修改表的方式加入主鍵,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每個表只能有一個主鍵。 (主鍵相當於聚合索引,是查詢最快的索引)。
6.2.4 全文索引
MySQL只有MyISAM儲存引擎支援FULLTEXT索引,並且類型別為CHAR、TEXT、VARCHAR。詳細參考同上。
6.2.5 外來鍵索引
如果表A的主關鍵字是表B中的欄位,則該欄位稱為表B的外來鍵,表A稱為主表,表B稱為從表。外來鍵是用來實現參照完整性的,不同的外來鍵約束方式將可以使兩張表緊密的結合起來,特別是修改或者刪除的級聯操作將使得日常的維護工作更加輕鬆。
**************************************************************************************************
* 轉載請註明出處:http://blog.csdn.net/jesseyoung/article/details/38037543 *
**************************************************************************************************