索引(Index)是幫助MySQL高效獲取數據的數據結構。
在MySQL中,索引屬於存儲引擎級別的概念,不一樣存儲引擎對索引的實現方式是不一樣的。MyISAM和InnoDB存儲引擎只支持BTREE索引,MEMORY/HEAP存儲引擎支持HASH和BTREE索引。 數據庫
A、提升數據檢索效率,下降數據庫的IO成本。
B、經過索引對數據進行排序,下降數據排序的成本,下降了CPU的消耗。
C、大大加快數據的查詢速度。網絡
A、建立索引和維護索引要耗費時間,而且隨着數據量的增長所耗費的時間也會增長
B、索引也須要佔空間,咱們知道數據表中的數據也會有最大上線設置的,若是咱們有大量的索引,索引文件可能會比數據文件更快達到上線值
C、當對錶中的數據進行增長、刪除、修改時,索引也須要動態的維護,下降了數據的維護速度。數據結構
A、主鍵自動創建惟一索引
B、頻繁做爲查詢條件的字段應該建立索引
C、查詢中與其餘表關聯的字段,外鍵關係創建索引
D、頻繁更新的字段不適合創建索引,由於每次更新不僅僅是更新了記錄還會更新索引
E、WHERE條件裏用不到的字段不建立索引
F、單鍵/組合索引的選擇問題,who?(在高併發下傾向建立組合索引)
G、查詢中排序的字段,排序的字段若經過索引去訪問將大大提升排序速度
H、查詢中統計或者分組字段
不適合使用索引的場合:
A、對常常更新的表就避免對其進行過多的索引,對常常用於查詢的字段應該建立索引。
B、數據量小的表最好不要使用索引,因爲數據較少,可能查詢所有數據花費的時間比遍歷索引的時間還要短,索引就可能不會產生優化效果。
C、在不一樣值少的列上不要創建索引,好比在學生表的"性別"字段上只有男,女兩個不一樣值。在一個不一樣值較多的列能夠創建索引。併發
單列索引只包含單個列,但一個表中能夠有多個單列索引。
A、普通索引
普通索引容許在定義索引的列中插入重複值和空值。
B、惟一索引
索引列中的值必須是惟一的,可是容許爲空值。
C、主鍵索引
主鍵索引是一種特殊的惟一索引,不容許有空值。數據庫設計
在表中的多個字段組合上建立的索引,只有在查詢條件中使用了組合的多個字段的左邊字段時,索引纔會被使用,使用複合索引時遵循最左前綴集合。ide
全文索引,只有MyISAM存儲引擎支持,只能在CHAR、VARCHAR、TEXT類型字段上使用全文索引。
全文索引主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。在數據量較大時候,先將數據放入一個沒有全文索引的表中,而後再用CREATE index建立fulltext索引,要比先爲一張表創建fulltext而後再將數據寫入的速度快不少。高併發
空間索引是對空間數據類型的字段創建的索引,MySQL中的空間數據類型有四種:GEOMETRY、POINT、LINESTRING、POLYGON。
在建立空間索引時,使用SPATIAL關鍵字。
空間索引必須使用MyISAM存儲引擎, 而且空間索引的字段必須爲非空。優化
建立表時建立索引的語法:網站
CREATE TABLE table_name[col_name data type] [UNIQUE|FULLTEXT|SPATIAL][INDEX|KEY][index_name](col_name[length])[asc|desc]
在表上建立索引的語法:設計
ALTER TABLE tablename ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [indexname] (col_name)[ASC|DESC]; CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] indexname ON tablename(col_name[length])[ASC|DESC];
unique|fulltext爲可選參數,分別表示惟一索引、全文索引
index和key爲同義詞,二者做用相同,用來指定建立索引
col_name爲須要建立索引的字段列,該列必須從數據表中該定義的多個列中選擇
index_name指定索引的名稱,爲可選參數,若是不指定,默認col_name爲索引值
length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度
asc或desc指定升序或降序的索引值存儲
在建立索引時若是不指定索引名,默認使用字段名做爲索引名。
直接建立索引CREATE INDEX index_name ON tablename(column(length))
修改表結構ALTER TABLE table_name ADD INDEX index_name ON (column(length))
建立表時指定索引
CREATE TABLE tablename ( col_name1 type, col_name2 type, INDEX index_name(col_name) );
索引列的值必須惟一,但容許有空值。若是是組合索引,則列值的組合必須惟一。
直接建立惟一索引CREATE UNIQUE INDEX indexName ON tablename(column(length))
修改表結構ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))
建立表時直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, UNIQUE INDEX index_name(col_name) );
修改表結構ALTER TABLE table_name ADD PRIMARY KEY(col_name)
建立表時直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, PRIMARY KEY(col_name) );
直接建立複合索引CREATE INDEX indexName ON tablename(col_name1,col_name2)
修改表結構ALTER TABLE table_name ADD INDEX indexName(col_name1,col_name2)
建立表時直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, INDEX index_name(col_name1,col_name2) );
直接建立全文索引CREATE FULLTEXT INDEX indexName ON tablename(col_name)
修改表結構ALTER TABLE table_name ADD FULLTEXT INDEX indexName(col_name)
建立表時直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, FULLTEXT INDEX index_name(col_name) );
在使用全文索引時,須要藉助MATCH AGAINST操做,而不是通常的WHERE語句加LIKE。全文索引的限制比較多,好比只能使用MyISAM存儲引擎,好比只能在CHAR、VARCHAR、TEXT上設置全文索引。好比搜索的關鍵字默認至少要4個字符,好比搜索的關鍵字過短就會被忽略掉。SELECT * FROM tablename WHERE MATCH(col_name) AGAINST('pattern');
col_name爲全文索引列,'pattern'爲匹配的字符串
DROP INDEX [indexName] ON tablename; ALTER TABLE tablename DROP INDEX indexname;
SHOW INDEX FROM table_name;
A、索引不會包含有null值的列
在數據庫設計時不要讓字段的默認值爲null。
B、使用短索引
C、索引列排序
所以數據庫默認排序能夠符合要求的狀況下不要使用排序操做;儘可能不要包含多個列的排序,若是須要最好給這些列建立複合索引。
D、like語句操做
通常狀況下不推薦使用like操做,若是非使用不可。like 「%aaa%」不會使用索引而like 「aaa%」可使用索引。
E、不要在列上進行運算
在索引列上進行運算將致使索引失效而進行全表掃描,例如SELECT * FROM table_name WHERE YEAR(column_name)<2017;
F、不使用not in和<>操做
create procedure addStudent(in num int) begin declare i int; set i=1; delete from TStudent; while num>=i do insert TStudent values ( LPAD(convert(i,char(10)),10,'0'), CreateName(), if(ceil(rand()*10)%2=0,'男','女'), RPAD(convert(ceil(rand()*1000000000000000000),char(18)),18,'0'), Concat(convert(ceil(rand()*10)+1980,char(4)),'-',LPAD(convert(ceil(rand()*12),char(2)),2,'0'),'-',LPAD(convert(ceil(rand()*28),char(2)),2,'0')), Concat(PINYIN(sname),'@hotmail.com'), case ceil(rand()*3) when 1 then '網絡與網站開發' when 2 then 'JAVA' ELSE 'NET' END, NOW() ); set i=i+1; end while; select * from TStudent; end
修改addStudent存儲過程,插入500000條記錄call addStudent(500000);
SQL語句查詢×××號cardID以12345開頭的學生。select * from TStudent where cardID like '12345%'
花費時間爲1.27秒
alter table TStudent add index cardidIndex(cardID);
SQL語句查詢×××號cardID以12345開頭的學生。select * from TStudent where cardID like '12345%'
花費時間31毫秒。
schoolDB數據庫索引佔用的磁盤空間。
SELECT CONCAT(ROUND(SUM(index_length)/(1024*1024), 2), ' MB') AS 'Total Index Size' FROM information_schema.TABLES WHERE table_schema LIKE 'schoolDB';
查看schoolDB數據庫數據佔用的磁盤空間。
SELECT CONCAT(ROUND(SUM(data_length)/(1024*1024), 2), ' MB') AS 'Total Data Size' FROM information_schema.TABLES WHERE table_schema LIKE 'schoolDB';
EXPLAIN能夠查看SQL查詢語句的查詢計劃,使用索引仍是全表掃描,key顯示使用的索引。explain select * from TStudent where cardid like '12345%' \G;
id: SELECT識別符,即SELECT的查詢序列號,一條語句中,select是第幾回出現。
select_type:所使用的SELECT查詢類型,SIMPLE表示爲簡單的SELECT,不實用UNION或子查詢。其餘取值,PRIMARY:最外面的SELECT在擁有子查詢時,就會出現兩個以上的SELECT。UNION:union(兩張錶鏈接)中的第二個或後面的select語句 SUBQUERY:在子查詢中,第二SELECT。
table:數據表的名字。按被讀取的前後順序排列。
type:指定本數據表和其餘數據表之間的關聯關係,表中全部符合檢索值的記錄都會被取出來和從上一個表中取出來的記錄做聯合。ref用於鏈接程序使用鍵的最左前綴或者鍵不是primary key或unique索引的狀況。取值有system、const、eq_ref、index和All。
possible_keys:MySQL在搜索數據記錄時能夠選用的各個索引
key:實際選用的索引
key_len:顯示MySQL使用索引的長度(使用的索引個數),當key字段的值爲 null時,索引的長度就是null。
ref:給出關聯關係中另外一個數據表中數據列的名字。
rows:MySQL在執行查詢時預計會從數據表裏讀出的數據行的個數。
extra:提供與關聯操做有關的信息。
一個包含查詢所需的字段的索引稱爲覆蓋索引(covering index)。MySQL只須要經過索引就能夠返回查詢所須要的數據,而沒必要在查到索引以後進行回表操做,減小IO,提供效率。
經過EXPLAIN查看SQL語句的執行計劃時,在EXPLAIN的Extra列出現Using Index提示時,說明SQL查詢使用覆蓋索引。
Tstudent表cardID列建立了索引,SQL語句查找的列是cardID,查找條件也是cardID,就會使用cardID索引進行查找,不須要掃描表的頁。explain select sname from TStudent where sname like '劉%';
執行結果Extra 出現using index,說明是使用覆蓋索引查找。
在MySQL中的ORDER BY有兩種排序實現方式:
A、利用有序索引獲取有序數據
B、文件排序
使用EXPLAIN分析SQL查詢時,利用有序索引獲取有序數據顯示Using index。而文件排序顯示Using filesort。explain select email from TStudent order by email;
email列沒有索引,SQL語句的查詢計劃能夠看到Extra是using filesort,說明是將結果在內存中排序,須要額外時間開銷。
給Email列添加索引後,
alter table TStudent add index emailIndex(email); explain select email from TStudent order by email;
再次執行,能夠看到Extra列是Using index,說明使用索引排序,沒有額外時間開銷。