索引是對數據庫表中一個或多個列(例如,user 表的姓名 (name) 列)的值進行排序的結構。若是想按特定職員的姓來查找他或她,則與在表中搜索全部的行相比,索引有助於更快地獲取信息。mysql
例如這樣一個查詢:select * from table1 where id=10000。若是沒有索引,必須遍歷整個表,直到ID等於10000的這一行被找到爲止;有了 索引以後(必須是在ID這一列上創建的索引),便可在索引中查找。因爲索引是通過某種算法優化過的,於是查找次數要少的多。可見,索引插敘的速度要比沒有索引的速度要快不少算法
MySQL中常見索引有:sql
1、普通索引(index)數據庫
普通因此只有一個功能,就是加快查找速度。操做以下服務器
一、先建立一個表ide
create table tab1( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, index ix_name (name) //添加索引,將Name列設置爲索引 )
二、建立表索引函數
create index 索引名稱 on 表名(列名)
三、刪除索引性能
drop 索引名稱 on 表名;
四、查看索引優化
show index from 表名;
五、注意事項(對於建立索引時若是是BLOB 和 TEXT 類型,必須指定length。)spa
create index index_name on tab1(extra(32));
2、惟一索引(unique)
惟一性索引unique index和通常索引normal index最大的差別就是在索引列上增長了一層惟一約束。添加惟一性索引的數據列能夠爲空,可是隻要存在數據值,就必須是惟一的。
一、建立表+惟一索引
create table tab2( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, unique ix_name (name) -- 重點在這裏 )
二、建立惟一索引
create unique index 索引名 on 表名(列名)
三、刪除惟一索引
drop unique index 索引名 on 表名
3、主鍵索引
在數據庫關係圖中爲表定義一個主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特殊類型。主鍵索引要求主鍵中的每一個值是惟一的。當在查詢中使用主鍵索引時,它還容許快速訪問數據。數據不能爲空
一、建立表+主鍵索引
create table in1( nid int not null auto_increment, name varchar(32) not null, email varchar(64) not null, extra text, primary key(nid), index pri_index (name) )
二、建立主鍵索引
alter table 表名 add primary key(列名);
三、刪除主鍵
alter table 表名 drop primary key; alter table 表名 modify 列名 int, drop primary key;
4、組合索引
組合索引,就是組合查詢的意思,將兩列或者多列組合成一個索引進行查詢
其應用場景爲:頻繁的同時使用n列來進行查詢,如:select * from where name = 'admin' and email = 'admin@163.com'。
一、建立表組合索引
create table tb3( nid int not null auto_increment primary key, name varchar(32) not null, email varchar(64) not null, extra text, index x_index (name,email) )
如上建立組合索引以後,查詢有的會使用索引,有的不會:
5、使用索引的注意事項
一、正確使用索引
數據庫表中添加索引後可以讓查詢數據庫速度飛快,但前提必須是正確的使用索引來查詢,若是以錯誤的方式使用,則即便創建索引也會不奏效。
下面這些狀況不會使用到索引:
1、like '%xx' select * from tb1 where name like '%cn'; 2、使用函數 select * from tb1 where reverse(name) = 'admin'; 3、or select * from tb1 where nid = 1 or email='admin@live.com'; 特別的:當or條件中有未創建索引的列才失效,如下會走索引 select * from tb1 where nid = 1 or name = 'admin'; select * from tb1 where nid = 1 or email = 'admin@live.com' and name = 'admin' 4、類型不一致 若是列是字符串類型,傳入條件是必須用引號引發來,否則... select * from tb1 where name = 999; 5、 != select * from tb1 where name != 'admin' 特別的:若是是主鍵,則仍是會走索引 select * from tb1 where nid != 123 6、 > select * from tb1 where name > 'admin' 特別的:若是是主鍵或索引是整數類型,則仍是會走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 7、order by select email from tb1 order by name desc; 當根據索引排序時候,選擇的映射若是不是索引,則不走索引 特別的:若是對主鍵排序,則仍是走索引: select * from tb1 order by nid desc; 8、 組合索引最左前綴 若是組合索引爲:(name,email) name and email -- 使用索引 name -- 使用索引 email -- 不使用索引
二、其餘注意事項
避免使用
select
*
count
(1)或
count
(列) 代替
count
(*)
建立表時儘可能時
char
代替
varchar
表的字段順序固定長度的字段優先
組合索引代替多個單列索引(常用多個條件查詢時)
儘可能使用短索引
使用鏈接(
JOIN
)來代替子查詢(Sub-Queries)
連表時注意條件類型需一致
索引散列值(重複少)不適合建索引,例:性別不適合
三、執行計劃
explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息能夠進行SQL優化
mysql> explain select * from tb2; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | tb2 | ALL | NULL | NULL | NULL | NULL | 2 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ 1 row in set (0.00 sec)
1 id 2 查詢順序標識 3 如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B; 4 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+ 5 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 6 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+ 7 | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL | 8 | 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where | 9 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+ 10 特別的:若是使用union鏈接氣值可能爲null 11 12 13 select_type 14 查詢類型 15 SIMPLE 簡單查詢 16 PRIMARY 最外層查詢 17 SUBQUERY 映射爲子查詢 18 DERIVED 子查詢 19 UNION 聯合 20 UNION RESULT 使用聯合的結果 21 ... 22 table 23 正在訪問的表名 24 25 26 type 27 查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const 28 ALL 全表掃描,對於數據表從頭至尾找一遍 29 select * from tb1; 30 特別的:若是有limit限制,則找到以後就不在繼續向下掃描 31 select * from tb1 where email = 'seven@live.com' 32 select * from tb1 where email = 'seven@live.com' limit 1; 33 雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就再也不繼續掃描。 34 35 INDEX 全索引掃描,對索引從頭至尾找一遍 36 select nid from tb1; 37 38 RANGE 對索引列進行範圍查找 39 select * from tb1 where name < 'alex'; 40 PS: 41 between and 42 in 43 > >= < <= 操做 44 注意:!= 和 > 符號 45 46 47 INDEX_MERGE 合併索引,使用多個單列索引搜索 48 select * from tb1 where name = 'alex' or nid in (11,22,33); 49 50 REF 根據索引查找一個或多個值 51 select * from tb1 where name = 'seven'; 52 53 EQ_REF 鏈接時使用primary key 或 unique類型 54 select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid; 55 56 57 58 CONST 常量 59 表最多有一個匹配行,由於僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,由於它們只讀取一次。 60 select nid from tb1 where nid = 2 ; 61 62 SYSTEM 系統 63 表僅有一行(=系統表)。這是const聯接類型的一個特例。 64 select * from (select nid from tb1 where nid = 1) as A; 65 possible_keys 66 可能使用的索引 67 68 key 69 真實使用的 70 71 key_len 72 MySQL中使用索引字節長度 73 74 rows 75 mysql估計爲了找到所需的行而要讀取的行數 ------ 只是預估值 76 77 extra 78 該列包含MySQL解決查詢的詳細信息 79 「Using index」 80 此值表示mysql將使用覆蓋索引,以免訪問表。不要把覆蓋索引和index訪問類型弄混了。 81 「Using where」 82 這意味着mysql服務器將在存儲引擎檢索行後再進行過濾,許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where子句的查詢都會顯示「Using where」。有時「Using where」的出現就是一個暗示:查詢可受益於不一樣的索引。 83 「Using temporary」 84 這意味着mysql在對查詢結果排序時會使用一個臨時表。 85 「Using filesort」 86 這意味着mysql會對結果使用一個外部索引排序,而不是按索引次序從表裏讀取行。mysql有兩種文件排序算法,這兩種排序方式均可以在內存或者磁盤上完成,explain不會告訴你mysql將使用哪種文件排序,也不會告訴你排序會在內存裏仍是磁盤上完成。 87 「Range checked for each record(index map: N)」 88 這個意味着沒有好用的索引,新的索引將在聯接的每一行上從新估算,N是顯示在possible_keys列中索引的位圖,而且是冗餘的。