創(chuàng)建索引是指在某個表的一列或多列上建立一個索引,以便提高對表的訪問速度。創(chuàng)建索引有3種方式,這3種方式分別是創(chuàng)建表的時候創(chuàng)建索引、在已經(jīng)存在的表上創(chuàng)建索引和使用ALTER TABLE語句來創(chuàng)建索引。本節(jié)將詳細講解這3種創(chuàng)建索引的方法。 CREATE TABLE index1 (id INT , name VARCHAR(20) , sex BOOLEAN , INDEX ( id) ); 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index1 \G *************************** 1. row *************************** Table: index1 Create Table: CREATE TABLE `index1` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `sex` tinyint(1) DEFAULT NULL, KEY `index1_id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,id字段上已經(jīng)建立了一個名為index1_id的索引。使用EXPLAIN語句可以查看索引是否被使用,SQL代碼如下: mysql> EXPLAIN SELECT * FROM index1 where id=1 \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: index1 type: ref possible_keys: index1_id key: index1_id key_len: 5 ref: const rows: 1 Extra: 1 row in set (0.00 sec) 上面結(jié)果顯示,possible_keys和key處的值都為index1_id。說明index1_id索引已經(jīng)存在,而且已經(jīng)開始起作用。 CREATE TABLE index2 (id INT UNIQUE , name VARCHAR(20) , UNIQUE INDEX index2_id ( id ASC) ); 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index2 \G *************************** 1. row *************************** Table: index2 Create Table: CREATE TABLE `index2` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, UNIQUE KEY `id` (`id`), UNIQUE KEY `index2_id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,id字段上已經(jīng)建立了一個名為index2_id的唯一性索引。這里的id字段可以沒有進行唯一性約束,也可以在該字段上成功創(chuàng)建唯一性索引。但是,這樣可能達不到提高查詢速度的目的。 CREATE TABLE index3 (id INT , info VARCHAR(20) , FULLTEXT INDEX index3_info ( info ) )ENGINE=MyISAM; 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index3 \G *************************** 1. row *************************** Table: index3 Create Table: CREATE TABLE `index3` ( `id` int(11) DEFAULT NULL, `info` varchar(20) DEFAULT NULL, FULLTEXT KEY `index3_info` (`info`) ) ENGINE=MyISAM DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,info字段上已經(jīng)建立了一個名為index3_info的全文索引。如果表的存儲引擎不是MyISAM存儲引擎,系統(tǒng)會提示"ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes"。 CREATE TABLE index4 (id INT , subject VARCHAR(30) , INDEX index4_st ( subject(10) ) ); 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index4 \G *************************** 1. row *************************** Table: index4 Create Table: CREATE TABLE `index4` ( `id` int(11) DEFAULT NULL, `subject` varchar(30) DEFAULT NULL, KEY `index4_st` (`subject`(10)) ) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,subject字段上已經(jīng)建立了一個名為index4_st的單列索引。細心的讀者可能會發(fā)現(xiàn),subject字段長度為20,而index4_st索引的長度只有10。這樣做的目的還是為了提高查詢速度。對于字符型的數(shù)據(jù),可以不用查詢?nèi)啃畔?,而只查詢其前面的若干字符信息?br> CREATE TABLE index5 (id INT , name VARCHAR(20) , sex CHAR(4) , INDEX index5_ns ( name, sex ) ); 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index5 \G *************************** 1. row *************************** Table: index5 Create Table: CREATE TABLE `index5` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `sex` char(4) DEFAULT NULL, KEY `index5_ns` (`name`,`sex`) ) ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,name和sex字段上已經(jīng)建立了一個名為index5_ns的單列索引。多列索引中,只有查詢條件中使用了這些字段中第一個字段時,索引才會被使用。用EXPLAIN語句可以查看索引的使用情況。如果只是有name字段作為查詢條件進行查詢,顯示結(jié)果如下: mysql> EXPLAIN select * from index5 where name='hjh' \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: index5 type: ref possible_keys: index5_ns key: index5_ns key_len: 83 ref: const rows: 1 Extra: Using index condition 1 row in set (0.00 sec) 結(jié)果顯示,possible_keys和key的值都是index5_ns。額外信息(Extra)顯示正在使用索引。這說明使用name字段進行索引時,索引index5_ns已經(jīng)被使用。如果只使用sex字段作為查詢條件進行查詢,顯示結(jié)果如下: mysql> EXPLAIN select * from index5 where sex='n' \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: index5 type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 1 Extra: Using where 1 row in set (0.00 sec) 此時的結(jié)果顯示,possible_keys和key的值都為NULL。額外信息(Extra)顯示正在使用Where條件查詢,而未使用索引。 CREATE TABLE index6 (id INT , space GEOMETRY NOT NULL, SPATIAL INDEX index6_sp (space ) )ENGINE=MyISAM; 運行結(jié)果顯示創(chuàng)建成功,使用SHOW CREATE TABLE語句查看表的結(jié)構(gòu)。顯示如下: mysql> SHOW CREATE TABLE index6 \G *************************** 1. row *************************** Table: index6 Create Table: CREATE TABLE `index6` ( `id` int(11) DEFAULT NULL, `space` geometry NOT NULL, SPATIAL KEY `index6_sp` (`space`) ) ENGINE=MyISAM DEFAULT CHARSET=utf81 row in set (0.00 sec) 結(jié)果可以看到,space字段上已經(jīng)建立了一個名為index6_sp的空間索引。值得注意的是,space字段是非空的,而且數(shù)據(jù)類型是GEOMETRY類型。這個類型是空間數(shù)據(jù)類型。空間類型包括GEOMETRY、POINT、LINESTRING和POLYGON類型等。這些空間數(shù)據(jù)類型平時很少用到。 什 么是索引? CODE: CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL ); 后,我們完全隨機把1000個不同name值插入到people表。 CODE: 創(chuàng)建索引,例如 CREATE INDEX <索引的名字>; ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表); 創(chuàng)建表的時候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) ); 唯一性索引 CODE: 創(chuàng)建索引,例如CREATE UNIQUE INDEX <索引的名字>; ON tablename (列的列表); 修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表); 創(chuàng)建表 的時候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) ); 主 鍵 CODE: CREATE TABLE people ( peopleid SMALLINT NOT NULL AUTO_INCREMENT, firstname CHAR(50) NOT NULL, lastname CHAR(50) NOT NULL, age SMALLINT NOT NULL, townid SMALLINT NOT NULL, PRIMARY KEY (peopleid) ); 下面是我們插入到這個people表的數(shù)據(jù): CODE: ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age); 由于索引文件以B-樹格式保存,MySQL能夠立即轉(zhuǎn)到合適的firstname,然后 再轉(zhuǎn)到合適的lastname,最后轉(zhuǎn)到合適的age。在沒有掃描數(shù)據(jù)文件任何一個記錄的情況下,MySQL就正確地找出了搜索的目標記錄! CODE: firstname,lastname,age firstname,lastname firstname 從 另一方面理解,它相當于我們創(chuàng)建了(firstname,lastname,age)、(firstname,lastname)以及 (firstname)這些列組合上的索引。下面這些查詢都能夠使用這個fname_lname_age索引: CODE: SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan'; SELECT peopleid FROM people WHERE firstname='Mike'; The following queries cannot use the index at all: SELECT peopleid FROM people WHERE lastname='Sullivan'; SELECT peopleid FROM people WHERE age='17'; SELECT peopleid FROM people WHERE lastname='Sullivan' AND age='17'; 選擇索引 列 CODE: SELECT age ## 不使用索引 FROM people WHERE firstname='Mike' ## 考慮使用索引 AND lastname='Sullivan' ## 考慮使用索引 這個查詢與前面的查詢略有不同,但仍屬于簡單查詢。由于age是在SELECT部分被引用,MySQL不會用它來限制列 選擇操作。因此,對于這個查詢來說,創(chuàng)建age列的索引沒有什么必要。下面是一個更復雜的例子: CODE: SELECT people.age, ##不使用索引 town.name ##不使用索引 FROM people LEFT JOIN town ON people.townid=town.townid ##考慮使用索引 WHERE firstname='Mike' ##考慮使用索引 AND lastname='Sullivan' ##考慮使用索引 與前面的例 子一樣,由于firstname和lastname出現(xiàn)在WHERE子句中,因此這兩個列仍舊有創(chuàng)建索引的必要。除此之外,由于town表的townid 列出現(xiàn)在join子句中,因此我們需要考慮創(chuàng)建該列的索引。 CODE: EXPLAIN SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age='17'; 這個命令將返回下面這種分析結(jié)果: |
|
來自: 沙門空海 > 《數(shù)據(jù)庫》