MySQL目前主要有如下幾種索引類型:html
//建表時創建
CREATE TABLE table_name[col_name data type] [unique|fulltext][index|key][index_name](col_name[length])[asc|desc]
注意:複合索引使用時要與索引名和關聯的列一一對應,若是想單獨對某個列進行索引操做,須要新建個以獨立的索引
說明java
1.unique|fulltext爲可選參數,分別表示惟一索引、全文索引 2.index和key爲同義詞,二者做用相同,用來指定建立索引 3.col_name爲須要建立索引的字段列,該列必須從數據表中該定義的多個列中選擇 4.index_name指定索引的名稱,爲可選參數,若是不指定,默認col_name爲索引值 5.length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度 6.asc或desc指定升序或降序的索引值存儲
索引的建立、修改、刪除node
一、使用ALTER TABLE 語句建立索引mysql
應用於表建立完成以後添加索引redis
ALTER TABLE 表名 ADD 索引類型 (unique,primary key,fulltext,index)[索引名](字段名)
//普通索引 alter table table_name add index index_name (column_list) ; //惟一索引 alter table table_name add unique (column_list) ; //主鍵索引 alter table table_name add primary key (column_list) ;
說明:
ALTER TABLE可用於建立普通索引、UNIQUE索引和PRIMARY KEY索引3種索引格式,
table_name是要增長索引的表名,column_list指出對哪些列進行索引,多列時各列之間用逗號分隔。
索引名index_name可選,缺省時,MySQL將根據第一個索引列賦一個名稱。另外,ALTER TABLE容許在單個語句中更改多個表,所以能夠同時建立多個索引。
二、使用CREATE INDEX 對錶增長索引算法
CREATE INDEX可用於對錶增長普通索引或UNIQUE索引,可用於建表時建立索引。sql
CREATE INDEX index_name ON table_name(username(length));
若是是CHAR,VARCHAR類型,length能夠小於字段實際長度;若是是BLOB和TEXT類型,必須指定 length。
//create只能添加這兩種索引; CREATE INDEX index_name ON table_name (column_list) CREATE UNIQUE INDEX index_name ON table_name (column_list)
table_name、index_name和column_list具備與ALTER TABLE語句中相同的含義,索引名不可選。另外,不能用CREATE INDEX語句建立PRIMARY KEY索引。
三、刪除索引數據庫
刪除索引可使用ALTER TABLE或DROP INDEX語句來實現。DROP INDEX能夠在ALTER TABLE內部做爲一條語句處理。緩存
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索引,所以不須要指定索引名。若是沒有建立PRIMARY KEY索引,但表具備一個或多個UNIQUE索引,則MySQL將刪除第一個UNIQUE索引。數據結構
若是從表中刪除某列,則索引會受影響。對於多列組合的索引,若是刪除其中的某列,則該列也會從索引中刪除。若是刪除組成索引的全部列,則整個索引將被刪除。
四、修改索引
mysql 是沒有內置修改索引操做的,須要先執行刪除操做在從新創建一個索引
五、查看索引
-若是查看索引前,沒有使用use db_name等命令指定具體的數據庫,則必須加上FROM db_name SHOW INDEX FROM table_name [FROM db_name] --若是查看索引前,沒有使用use db_name等命令指定具體的數據庫,則必須加上db_name.前綴 SHOW INDEX FROM [db_name.]table_name --若是查看索引前,使用了use db_name等命令指定具體的數據庫 SHOW INDEX FROM table_name
組合索引與前綴索引
組合索引和前綴索引是對創建索引技巧的一種稱呼,並非索引的類型。
create table dm_user ( ID int not null auto_increment comment '主鍵', LOGIN_NAME varchar(30) not null comment '登陸名', PASSWORD varchar(30) not null comment '密碼', CITY varchar(30) not null comment '城市', AGE int not null comment '年齡', SEX int not null comment '性別(0:女 1:男)', primary key (ID) ); comment 表示添加註釋(注意中文亂碼的問題,須要設置表的編碼格式爲utf-8)
創建組合索引,即將LOGIN_NAME,CITY建到一個索引裏
ALTER TABLE md_user ADD INDEX name_city (LOGIN_NAME(16),CITY);
建表時,LOGIN_NAME長度爲30,這裏用16,是由於通常狀況下名字的長度不會超過16,這樣會加快索引查詢速度,還會減小索引文件的大小,提升INSERT,UPDATE的更新速度。
值得一提的是,mysql組合索引是依據「最左前綴」的形式產生索引結果的。簡單的理解就是隻從最左邊的開始組合,並非只要包含這幾列的查詢都會用到該組合索引。也就是說index_name(column1(length),column2,column3...)從左到右進行索引,若是沒有左前索引,mysql不會執行索引查詢。
ALTER TABLE table_name ADD INDEX index_name (column1,column2,column3,column4); //至關於分別建立了一下幾種組合索引 column1,column2,column3,column4 column1,column2,column3 column1,column2 column1
若是索引列長度過長,這種列索引時將會產生很大的索引文件,不便於操做,可使用前綴索引方式進行索引,前綴索引應該控制在一個合適的點,控制在0.31黃金值便可(大於這個值就能夠建立)。
SELECT COUNT(DISTINCT(LEFT(`column_name`,10)))/COUNT(*) FROM table_name; -- 這個值大於0.31就能夠建立前綴索引,Distinct去重複 ALTER TABLE `table_name` ADD INDEX `uname`(column_name(10)); -- 增長前綴索引SQL,將列名的索引創建在10,這樣能夠減小索引文件大小,加快索引查詢速度 Mysql字符串截取函數:left()、right()、substring()、substring_index()
索引類型
一、FULLTEXT
全文索引,目前只有MyISAM引擎支持,mysql 5.6以後InnoDB引擎也支持。其能夠在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上能夠建立全文索引。
注意:在數據量較大時候,先將數據放入一個沒有全文索引的表中,而後再用CREATE INDEX建立FULLTEXT索引,要比先爲一張表創建FULLTEXT而後再將數據寫入的速度快不少。
全文索引的出現是爲了解決WHERE name LIKE 「%keyword%"這類針對文本的模糊查詢效率較低的問題。
在數據量較大時是查詢是極其的耗時的,若是沒有異步IO處理,進程將被挾持,很浪費時間。想了解異步IO的,自行谷歌。
全文索引的使用:
建立ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);
使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('keyword' MODE );
其中, MODE爲搜尋方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。
關於這三種搜尋方式,簡單地說分爲:
FULLTEXT索引也是按照分詞原理創建索引的。西文中,大部分爲字母文字,分詞能夠很方便的按照空格進行分割。
但很中文不能按照這種方式進行分詞。那又怎麼辦呢?利用Mysql的中文分詞插件Mysqlcft,就能夠對中文進行分詞,Mysqlcft詳情。
二、HASH
hash就是一種(key=>value)形式的鍵值對,如數學中的函數映射,容許多個key對應相同的value,但不容許一個key對應多個value。正是因爲這個特性,hash很適合作索引,爲某一列或幾列創建hash索引,就會利用這一列或幾列的值經過必定的算法計算出一個hash值,對應一行或幾行數據(這裏在概念上和函數映射有區別,不要混淆)。在java語言中,每一個類都有本身的hashcode()方法,沒有顯示定義的都繼承自object類,該方法使得每個對象都是惟一的,在進行對象間equal比較,和序列化傳輸中起到了很重要的做用。
hash的生成方法有不少種,能夠保證hash碼的惟一性。如在MongoDB中,每個document都有系統爲其生成的惟一的objectID(包含時間戳,主機散列值,進程PID,和自增ID)也是一種hash的表現。
因爲hash索引能夠一次定位,不須要像樹形索引那樣逐層查找,所以具備極高的效率。
那爲何還須要其餘的樹形索引呢?
這裏簡單說下樹形索引Btree 與 Hash 索引的區別:
(1)Hash 索引僅能知足"=","IN"和"<=>"查詢,不能使用範圍查詢。
因爲 Hash 索引比較的是進行 Hash 運算以後的 Hash 值,因此它只能用於等值的過濾,不能用於基於範圍的過濾,由於通過相應的 Hash 算法處理以後的 Hash 值的大小關係,並不能保證和Hash運算前徹底同樣。
(2)Hash 索引沒法被用來避免數據的排序操做。
因爲 Hash 索引中存放的是通過 Hash 計算以後的 Hash 值,並且Hash值的大小關係並不必定和 Hash 運算前的鍵值徹底同樣,因此數據庫沒法利用索引的數據來避免任何排序運算;
(3)Hash 索引不能利用部分索引鍵查詢。
對於組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合併後再一塊兒計算 Hash 值,而不是單獨計算 Hash 值,因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也沒法被利用。
(4)Hash 索引在任什麼時候候都不能避免表掃描。
Hash 索引是將索引鍵經過 Hash 運算以後,將 Hash運算結果的 Hash 值和所對應的行指針信息存放於一個 Hash 表中,因爲不一樣索引鍵存在相同 Hash 值,因此即便取知足某個 Hash 鍵值的數據的記錄條數,也沒法從 Hash 索引中直接完成查詢,仍是要經過訪問表中的實際數據進行相應的比較,並獲得相應的結果。
(5)Hash 索引遇到大量Hash值相等的狀況後性能並不必定就會比B-Tree索引高。
對於選擇性比較低的索引鍵,若是建立 Hash 索引,那麼將會存在大量記錄指針信息存於同一個 Hash 值相關聯。這樣要定位某一條記錄時就會很是麻煩,會浪費屢次表數據的訪問,而形成總體性能低下。
HASH索引的過程,當咱們爲某一列或某幾列創建hash索引時(目前就只有MEMORY引擎顯式地支持這種索引),會在硬盤上生成相似以下的文件:
hash值 | 存儲地址 |
1db54bc745a1 | 77#45b5 |
4bca452157d4 | 76#4556,77#45cc… |
…
hash值即爲經過特定算法由指定列數據計算出來,磁盤地址即爲所在數據行存儲在硬盤上的地址(也有多是其餘存儲地址,其實MEMORY會將hash表導入內存)。
當進行WHERE num= 18 查詢時,會將18經過相同的算法計算出一個hash值==>在hash表中找到對應的儲存地址==>根據存儲地址取得數據。
因此,每次查詢時都要遍歷hash表,直到找到對應的hash值,如第(4)區別中描述的,數據量大了以後,hash表也會變得龐大起來,性能降低,遍歷耗時增長,如第(5)區別。
三、BTREE
BTREE樹形索引就是一種將索引值按必定的算法,存入一個樹形的數據結構中,學過數據結構的對於二叉樹這種數據結構應該不陌生吧。如二叉樹同樣,每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf。
BTREE在MyISAM裏的形式和Innodb稍有不一樣(雖然二者都使用B+Tree做爲索引結構,但仍是有些區別的,數據庫優化-mysql中INNODB和MYIASM引擎的區別)
在 Innodb裏,有兩種形態:一是primary key形態,其leaf node裏存放的是數據,並且不只存放了索引鍵的數據,還存放了其餘字段的數據。二是secondary index,其leaf node和普通的BTREE差很少,只是還存放了指向主鍵的信息.
而在MyISAM裏,主鍵和其餘的並無太大區別。不過和Innodb不太同樣的地方是在MyISAM裏,leaf node裏存放的不是主鍵的信息,而是指向數據文件裏的對應數據行的地址信息.
四、RTREE
RTREE在mysql不多使用,僅支持geometry數據類型(幾何數據),支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。
相對於BTREE,RTREE的優點在於範圍查找.
索引的缺點:
注意事項和設計技巧:
1.索引不會包含有null值的列
只要列中包含有null值都將不會被包含在索引中,組合索引中只要有一列含有null值,那麼這一列對於此複合索引就是無效的。因此咱們在數據庫設計時不要讓字段的默認值爲null。
2.使用短索引
對串列進行索引,若是可能應該指定一個前綴長度。例如,若是有一個char(255)的列,若是在前10個或20個字符內,多數值是唯一的,那麼就不要對整個列進行索引。短索引不只能夠提升查詢速度並且能夠節省磁盤空間和I/O操做。
3.索引列排序
查詢只使用一個索引,所以若是where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。所以數據庫默認排序能夠符合要求的狀況下不要使用排序操做;儘可能不要包含多個列的排序,若是須要最好給這些列建立複合索引。
4.like語句操做
通常狀況下不推薦使用like操做,若是非使用不可,如何使用也是一個問題。like 「%aaa%」 不會使用索引而like 「aaa%」可使用索引。
5.不要在列上進行運算
這將致使索引失效而進行全表掃描
6.不使用not in和<>判斷操做
NOT IN 、<>、!=不使用索引,但<,<=,=,>,>=,BETWEEN,IN是能夠用到索引的。
not in和<> 這將致使索引失效,能夠考慮使用exists 或 not exists 來代替in 和 not in (注意 in操做 是能夠利用索引的)。
mysql中的in語句是把外表和內表做hash 鏈接,而exists語句是對外表做loop循環,每次loop循環再對內表進行查詢。一直你們都認爲exists比in語句的效率要高,這種說法實際上是不許確的。這個是要區分環境的。
簡而言之就是,內查詢循環次數少(即內查詢表數據少於外查詢表或相差不大的狀況)使用exists 效率高;反之,外查詢循環次數少(即外查詢表遠少於內查詢表數據)使用in 效率高。
not in 和not exists若是查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;而not extsts 的子查詢依然能用到表上的索引。因此不管那個表大,用not exists都比not in要快。
使用between and 區間 來代替<>判斷操做。
七、EXPLAIN能夠幫助開發人員分析SQL問題.
explain顯示了mysql如何使用索引來處理select語句以及鏈接表,能夠幫助選擇更好的索引和寫出更優化的查詢語句。使用方法,在select語句前加上Explain就能夠。
八、索引要創建在值比較惟一的字段上
九、索引要創建在常常進行select操做的字段上。
這是由於,若是這些列不多用到,那麼有無索引並不能明顯改變查詢速度。相反,因爲增長了索引,反而下降了系統的維護速度和增大了空間需求。
十、對於那些定義爲text、image和bit數據類型的列不該該增長索引。由於這些列的數據量要麼至關大,要麼取值不多。
十一、在where和join中出現的列須要創建索引
十二、若是where字句的查詢條件裏使用了函數(如:where YEAR(column)=…),mysql將沒法使用索引
1三、在join操做中(須要從多個數據表提取數據時),mysql只有在主鍵和外鍵的數據類型相同時才能使用索引,不然及時創建了索引也不會使用。
1四、當where條件中存在 字符串與數字比較時(數據類型相同)不使用索引,用到OR 關鍵詞時也不會使用索引
各類索引的使用狀況
(1)對於BTREE這種Mysql默認的索引類型,具備廣泛的適用性
(2)因爲FULLTEXT對中文支持不是很好,在沒有插件的狀況下,最好不要使用。在小的博客應用,在數據採集時,爲其創建關鍵字列表,經過關鍵字索引也能夠起到類型的做用。
(3)對於一些搜索引擎級別的應用來講,FULLTEXT一樣不是一個好的處理方法,Mysql的全文索引創建的文件仍是比較大的,並且效率不是很高。Apache的Lucene或許是你的選擇。
(4)正是由於hash表在處理較小數據量時具備無可比擬的素的優點,因此hash索引很適合作緩存(內存數據庫)。如mysql數據庫的內存版本Memsql,使用量很普遍的緩存工具Mencached,NoSql數據庫redis等,都使用了hash索引這種形式。Mysql的MEMORY引擎也是能夠知足這種需求的。
在實際操做過程當中,應該選取表中哪些字段做爲索引?
爲了使索引的使用效率更高,在建立索引時,必須考慮在哪些字段上建立索引和建立什麼類型的索引,有7大原則:
1.選擇惟一性索引2.爲常常須要排序、分組和聯合操做的字段創建索引3.爲常做爲查詢條件的字段創建索引4.限制索引的數目5.儘可能使用數據量少的索引6.儘可能使用前綴來索引7.刪除再也不使用或者不多使用的索引