什麼是索引數據庫
索引是對數據庫表中一列或者多列的值進行排序的一種結構,所引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL必須從第一條記錄開始讀完整個表,直到找出相關的行。表越大,查詢數據所花費的時間越多,若是表中查詢的列有一個索引,MySQL能快速到達一個位置去搜索數據文件,而沒必要查看全部數據。性能
索引的含義和特色優化
索引是一個單獨的、存儲在磁盤上的數據庫結構,它們包含着對數據表裏全部記錄的引用指針。使用索引用於快速找出在某個或多個列中有一特定值的行,全部MySQL列類型均可以被索引,對相關列使用索引是提升查詢操做速度的最佳途徑。spa
例如,數據庫裏面有20000條記錄,如今要執行這麼一個查詢:SELECT * FROM table where num = 10000。若是沒有索引,必須遍歷整個表,直到num等於10000的這一行被找到爲止;若是在num列上建立索引,MySQL不須要任何掃描,直接在索引中找10000,就能夠得知值這一行的位置。可見,索引的創建能夠提升數據庫的查詢速度。設計
索引是在存儲引擎中實現的,所以,每種存儲引擎的索引都不必定徹底相同,而且每種存儲引擎也不必定支持全部索引類型。全部存儲引擎支持每一個表至少16個索引,總索引長度至少爲256字節。大多數存儲引擎有更高的額限制,MySQL中索引的存儲類型有兩種:BTREE和HASH,具體和表的存儲引擎相關;MyISAM和InnoDB存儲引擎只支持BTREE索引,MEMORY/HEAP存儲引擎能夠支持HASH和BTREE縮影。指針
索引的優勢主要有:code
一、經過建立惟一索引,能夠保證數據庫表中每一行數據的惟一性blog
二、能夠大大加快數據的查詢速度,這也是建立索引最主要的緣由排序
三、在實現數據的參考完整性方面,能夠加速表和表之間的鏈接索引
四、在使用分組和排序子句進行數據查詢時,也能夠顯著減小查詢中分組和排序的時間
增長索引也有許多不利的方面,好比:
一、建立索引和維護索引要耗費時間,而且隨着數據量的增長所耗費的時間也會增長
二、索引須要佔用磁盤空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是有大量的索引,索引文件可能比數據文件更快達到最大文件尺寸
三、當對錶中數據進行增長、刪除和修改的時候,索引也要動態地維護,這樣就下降了數據的維護速度
索引的分類
MySQL的索引能夠分爲如下幾類:
一、普通索引和惟一索引
(1)普通索引是MySQL中的基本索引類型,容許在定義索引的列中插入重複值和空值
(2)惟一索引,索引列的值必須惟一,但容許有空值,主鍵索引是一種特殊的惟一索引,不容許有空值
二、單列索引和組合索引
(1)單列索引即一個索引只包含單個列,一個表能夠有多個單列索引
(2)組合索引指在表的多個字段組合上建立的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引纔會被使用
三、全文索引
全文索引類型爲FULLTEXT,在定義索引的列上支持值的全文查找,容許在這些索引列中插入重複值和空值。全文索引能夠在CHAR、VARCHAR或者TEXT類型的列上建立,MySQL中只有MyISAM存儲引擎支持全文索引
索引的設計原則
索引設計不合理或者缺乏索引都會對數據庫和應用程序的性能形成障礙,高效的索引對於得到良好的性能很是重要,設計索引時,應該考慮一下:
一、索引並不是越多越好,一個表中若有大量的索引,不只佔用磁盤空間,並且會影響INSERT、DELETE、UPDATE等語句的性能,由於當表中的數據更改的同時,索引也會進行調整和更新
二、避免對常常更新的表設計過多的索引,而且索引中的列儘量要少,而對常常用於查詢的字段應該建立索引,但要避免添加沒必要要的字段
三、數據量小的表最好不要使用索引,因爲數據較少,查詢花費的時間可能比遍歷索引時間還要短,索引可能不會產生優化效果
四、在條件表達式中常常用到的不一樣值較多的列上創建索引,在不一樣值較少的列上不要創建索引,好比性別字段只有男和女,就不必創建索引。若是創建索引不但不會提升查詢效率,反而會嚴重下降更新速度
五、當惟一性是某種數據自己的特徵時,指定惟一索引。使用惟一索引需能確保定義的列的數據完整性,以提升查詢速度
六、在頻繁排序或分組(即group by或order by操做)的列上創建索引,若是待排序的列有多個,能夠在這些列上創建組合索引
建立表的時候建立索引
使用CREATE TABLE建立表的時候,除了能夠定義列的數據類型,還能夠定義主鍵約束、外鍵約束或者惟一性約束,而不論建立哪一種約束,在定義約束的同時至關於在指定列上建立了一個索引。建立表時建立索引的基本語法以下:
CREATE TABLE table_name[col_name data_type] [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [index_name](col_name[length]) [ASC|DESC]
解釋一下:
一、UNIQUE、FULLTEXT和SPATIAL爲可選參數,分別表示惟一索引、全文索引和空間索引
二、INDEX和KEY爲同義詞,兩者做用相同,用來指定建立索引
三、col_name爲須要建立索引的字段列,該列必須從數據表中該定義的多個列中選擇
四、index_name爲指定索引的名稱,爲可選參數,若是不指定則MySQL默認col_name爲索引值
五、length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度
六、ASC或DESC指定升序或者降序的索引值存儲
下面建立一個普通索引,沒有惟一性之類的限制,其做用只是加快對於數據的訪問速度:
CREATE TABLE book ( bookId INT NOT NULL, bookName VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, info VARCHAR(255) NOT NULL, year_publication YEAR NOT NULL, INDEX(year_publication) )
確認一下索引是否正在使用,可使用EXPLAIN:
EXPLAIN select * from book where yead_publication = 1990
結果爲:
解釋下字段的意思:
一、select_type行指定所使用的SELECT查詢類型,這裏值爲SIMPLE,表示簡單的SELECT,不使用UNION或者子查詢。其餘可能的取值有:PRIMARY、UNION、SUBQUERY等
二、table行指定數據庫讀取的數據表的名字,它們按照被讀取的前後順序排列
三、type行指定了本數據表與其餘數據表之間的關聯關係,可能的去只有system、const、eq_ref、ref、range、index和All
四、possible_keys行給出了MySQL在搜索數據記錄時可選用的各個索引
五、key行是MySQL使用的實際索引
六、key_len行給出了索引按字節計算的長度,key_len數值越小,表示越快
七、ref行給出了關聯關係中另一個數據表裏的數據列的名字
八、rows行是MySQL在執行這個查詢時預計會從這個數據表裏讀出的數據行的個數
九、extra行提供了與關聯操做有關的信息
看到,possible_keys和key的值都爲year_publication,查詢時使用了索引
二、建立惟一索引
惟一索引和普通索引相似,不過惟一索引索引列的值必須惟一,但容許有空值,若是是組合索引,則列值的組合必須惟一。看一下建立惟一索引的方式:
CREATE TABLE uniquetable ( id INT NOT NULL, name CHAR(30) NOT NULL, UNIQUE INDEX UniqIdx(id) )
這就在表的id字段上建立了一個名爲UniqIdx的惟一索引
三、建立單列索引
單列索引是在數據表中的某一個字段上建立的索引,一個表中能夠建立多個單列索引,前面兩個例子中建立的索引都是單列索引,好比:
CREATE TABLE singletable ( id INT NOT NULL, name CHAR(30) NOT NULL, UNIQUE INDEX SingleIdx(name(20)) )
這就在name字段上創建了一個名爲SingleIdx的單列索引,索引長度爲20
四、建立組合索引
組合索引是在多個字段上建立一個索引,好比:
create table uniontable ( id INT NOT NULL, name CHAR(30) NOT NULL, age INT NOT NULL, info VARCHAR(255), INDEX UnionIdx(id, name, age) )
這就爲id、name和age三個字段成功建立了一個名爲UnionIdx的組合索引
五、建立全文索引
全文索引能夠對全文進行搜索,只有MyISAM存儲引擎支持全文索引,而且只爲CHAR、VARCHAR和TEXT列,索引老是對整個列進行,不支持局部索引,好比:
CREATE TABLE fulltexttable ( id INT NOT NULL, name CHAR(30) NOT NULL, age INT NOT NULL, info VARCHAR(255), FULLTEXT INDEX FullTxtIdx(info) )ENGINE=MyISAM
由於默認的存儲引擎爲InnoDB,而全文索引只支持MyISAM,因此這裏建立表的時候要手動指定一下引擎。
看到這麼建立,就在info字段上成功創建了一個名爲FullTxtIdx的FULLTEXT全文索引,全文索引很是適合大型數據庫,而對於小的數據集,它的用處可能比較小
在已經存在的表上建立索引
在已經存在的表上建立索引,可使用ALTER TABLE語句或者CREATE INDEX語句,因此,分別講解一下如何使用ALTER TABLE和CREATE INDEX語句在已知的表字段上建立索引。
一、使用ALTER TABLE語句建立索引
ALTER TABLE建立索引的基本語法爲:
ALTER TABLE table_name ADD [UNIQUE|FUUTEXT|SPATIAL] [INDEX|KEY] [index_name] (col_name[length],...) [ASC|DESC]
與建立表時建立索引的語法不一樣的是,這裏用了ALTER TABLE和ADD關鍵字,ADD表示向表中添加索引。以book這張表爲例,先看一下這張表裏面有哪些索引:
SHOW INDEX FROM book
看下結果:
解釋一下:
一、table表示建立索引的表
二、Non_unique表示索引不是一個惟一索引,1表示非惟一索引,0表示惟一索引
三、Key_name表示索引的名稱
四、Seq_in_index表示該字段在索引中的位置,單列索引改值該值爲1,組合索引爲每一個字段在索引中定義的順序
五、Column_name表示定義索引的列字段
六、Sub_part表示索引的長度
七、Null表示該字段是否能爲空值
八、Index_type表示索引類型
因此,book裏面已經有一個索引了,是一個非惟一索引,如今給bookname字段加上索引,SQL語句以下:
ALTER TABLE book ADD INDEX BoNameIdx(bookname(30));
再給bookId字段加上惟一索引,名稱爲UniqidIdx:
ALTER TABLE book ADD UNIQUE INDEX UniqidIdx(bookId);
再給author字段加上單列索引:
ALTER TABLE book ADD INDEX BkauthorIdx(author(50));
意思是查詢的時候,只須要檢索前面50個字符。這裏專門提一下,對字符串類型的字段進行索引,若是可能應該指定一個前綴長度,例如,一個CHAR(255)的列,若是在前10個或者前30個字符內,多數值是惟一的,則不須要對整個列進行索引,短索引不只能夠提升查詢速度並且能夠節省磁盤空間、減小I/O操做
組合索引和全文索引和建立表時創建索引的方式差很少,就不寫了,此時咱們SHOW一下INDEX:
二、使用CREATE INDEX語句建立索引
CREATE INDEX語句能夠在已經存在的表上添加索引,MySQL中CREATE INDEX被映射到一個ALTER TABLE語句上,基本語法結構爲:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name ON table_name(col_name[length],...)[ASC|DESC]
看到和ALTER INDEX語句的語法基本同樣,下面把book表刪除了再建立,全部字段都沒有索引,用CREATE INDEX語句建立一次索引:
-- 爲bookname字段創建名爲BkNameIdx的普通索引 CREATE INDEX BkNameIdx ON book(bookname); -- 爲bookid字段創建名爲UniqidIdx的惟一索引 CREATE INDEX UniqidIdx ON book(bookid); -- 爲author和info字段創建名爲BkAuAndInfoIdx的組合索引 CREATE INDEX BkAuAndInfoIdx ON book(author(20), info(50)); -- 爲year_publication字段創建名爲BkyearIdx的普通索引 CREATE INDEX BkyearIdx ON book(year_publication);
此時咱們SHOW一下INDEX,能夠看到爲5個字段創建了4個索引:
刪除索引
最後一項工做就是刪除索引了,可使用ALTER TABLE和DROP INDEX刪除索引。
一、ALTER TABLE
ALTER TABLE的基本語法爲:
ALTER TABLE table_name DROP INDEX index_name
好比把book的UniqidIdx給刪除了:
ALTER TABLE book DROP INDEX UniqidIdx;
這樣就刪除了book表中的UniqidIdx這個索引,能夠SHOW INDEX from book查看一下,這裏就不貼圖了
二、DROP INDEX
DROP INDEX的基本語法爲:
DROP INDEX index_name ON table_name
好比我把BkAuAndInfoIdx這個組合索引給刪了:
DROP INDEX BkAuAndInfoIdx ON book
這樣就把book表裏面的BkAuAndInfoIdx這個組合索引給刪除了。
注意一個細節,刪除表中的列時,若是要刪除的列爲整個索引的組成部分,則該列也會從索引中刪除;若是組成索引的全部列都被刪除,則整個索引將被刪除