什麼是索引?爲何要創建索引?索引分類?索引的使用?轉載SQL(五) MySQL中的索引詳講html
索引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL必須從第一條記錄開始讀完整個表,直到找出相關的行,表越大查詢數據所花費的時間就越多。若是表中查詢的列有索引,MySQL可以快速到達一個位置去搜索數據文件,而沒必要查看全部數據,那麼將會節省很大一部分時間。mysql
例如:有一張person表,其中有2W條記錄,記錄着2W我的的信息。有一個Phone的字段記錄每一個人的電話號碼,如今想要查詢出電話號碼爲xxxx的人的信息。算法
若是沒有索引,那麼將從表中第一條記錄一條條往下遍歷,直到找到該條信息爲止。sql
若是有了索引,那麼會將 Phone 字段,經過必定的方法進行存儲,好讓查詢該字段上的信息時,可以快速找到對應的數據,而沒必要在遍歷2W條數據了。其中MySQL中的索引的存儲類型有兩種:BTREE、HASH。 也就是用樹或者Hash值來存儲該字段,更詳細的查找邏輯就須要會算法的知識了。咱們如今只須要知道索引的做用,功能是什麼就行。服務器
優勢:併發
一、全部的MySql列類型(字段類型)均可以被索引,也就是能夠給任意字段設置索引。優化
二、大大加快數據的查詢速度。spa
缺點:操作系統
一、建立索引和維護索引要耗費時間,而且隨着數據量的增長所耗費的時間也會增長。3d
二、索引也須要佔空間,咱們知道數據表中的數據也會有最大上線設置的,若是咱們有大量的索引,索引文件可能會比數據文件更快達到上線值。
三、當對錶中的數據進行增長、刪除、修改時,索引也須要動態的維護,下降了數據的維護速度。
使用原則:
經過上面說的優勢和缺點,咱們應該能夠知道,並非每一個字段都設置爲索引好,也不是索引越多越好,而是須要本身合理的使用。
一、對常常更新的表就避免對其設置過多的索引,對常常用於查詢的字段應該建立索引。
二、數據量小的表最好不要使用索引,由於因爲數據較少,可能查詢所有數據花費的時間比遍歷索引的時間還要短,索引就可能不會產生優化效果。
三、在一個列上(字段上)不一樣值較少的不要創建索引,好比在學生表的"性別"字段上只有男,女兩個不一樣值。相反的,在一個字段上不一樣值較多的但是創建索引。
以上簡單的說下索引的優缺點,在之後的使用中再慢慢總結。
索引是在存儲引擎中實現的,也就是說不一樣的存儲引擎,會使用不一樣的索引:
MyISAM和InnoDB存儲引擎:只支持BTREE索引, 也就是說默認使用BTREE,不可以更換。(可是innoDB存儲引擎支持hash索引是自適應的,innoDB存儲引擎會根據表的使用狀況自動爲表生成hash索引,不能人爲干預是否在一張表中生成hash索引。後續再整理)
MEMORY/HEAP存儲引擎:支持HASH和BTREE索引。
存儲引擎的類型及特色:
引擎名稱 |
優勢 |
缺陷 |
應用場景 |
MyISAM |
獨立於操做系統,這說明能夠輕鬆地將其從Windows服務器移植到Linux服務器 |
不支持事務/行級鎖/外鍵約束 |
適合管理郵件或Web服務器日誌數據 |
InnoDB |
健壯的事務型存儲引擎;支持事務/行級鎖/外鍵約束自動災難恢復/AUTO_INCREMENT |
|
須要事務支持,而且有較高的併發讀取頻率 |
MEMORY |
爲獲得最快的響應時間,採用的邏輯存儲介質是系統內存 |
當mysqld守護進程崩潰時,全部的Memory數據都會丟失;不能使用BLOB和TEXT這樣的長度可變的數據類型 |
臨時表 |
MERGE |
是MyISAM類型的一種變種。合併表是將幾個相同的MyISAM表合併爲一個虛表 |
|
常應用於日誌和數據倉庫 |
ARCHIVE |
歸檔的意思,支持索引,擁有很好的壓縮機制 |
僅支持插入和查詢功能 |
常常被用來當作倉庫使用 |
索引咱們分爲四類:單列索引(普通索引,惟一索引,主鍵索引)、組合索引、全文索引、空間索引。
一、普通索引:MySQL中基本索引類型,沒有什麼限制,容許在定義索引的列中插入重複值和空值,純粹爲了查詢數據更快一點。
二、惟一索引:索引列中的值必須是惟一的,可是容許爲空值,
三、主鍵索引:是一種特殊的惟一索引,不容許有空值。
在建立空間索引時,使用SPATIAL關鍵字。
要求,引擎爲MyISAM,建立空間索引的列,必須將其聲明爲NOT NULL。具體細節看下面
Ⅰ、在建立表時建立索引:
建立索引:單列索引(普通、惟1、主鍵)、組合索引、全文索引和空間索引。
格式:CREATE TABLE 表名[字段名 數據類型] [UNIQUE|FULLTEXT|SPATIAL|...] [INDEX|KEY] [索引名字] (字段名[length])
一、建立普通索引:
## 建立普通索引,建立索引時未指定索引的名,會自動幫咱們用字段名看成索引名
CREATE TABLE book( id INT NOT NULL PRIMARY KEY, name VARCHAR(50) NOT NULL, author VARCHAR(20) NOT NULL, info VARCHAR(255) NULL, INDEX(author));
## 查看錶的建立
SHOW CREATE TABLE book; -------------------------------結果---------------------------------- CREATE TABLE `book` ( `id` int(11) NOT NULL, `name` varchar(50) NOT NULL, `author` varchar(20) NOT NULL, `info` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `author` (`author`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
## 用EXPLAIN關鍵字,來查看索引是否正在被使用,而且輸出其使用的索引信息
EXPLAIN SELECT * FROM book WHERE author = 'nana';
---------------------------------結果--------------------------------
雖然表中沒數據,可是有EXPLAIN關鍵字,用來查看索引是否正在被使用,而且輸出其使用的索引的信息。
id:爲SELECT的識別符。這是SELECT的查詢序列號,也就是一條語句中,該select是第幾回出現。在上面語句中,select只有一個,因此是1。
select_type:表示使用SELECT的查詢類型,SIMPLE表示爲簡單的SELECT,不適用於UNION或子查詢,就是簡單的SELECT。也就是說該SELECT查詢時會使用索引。其餘取值:
PRIMARY:最外面的SELECT,在有子查詢時,就會出現兩個以上的SELECT。
UNION:union(兩張錶鏈接)中的第二個或後面的select語句。
SUBQUERY:在子查詢中,第二個SELECT。
table:數據表的名字。按照被讀取的前後順序排列,這裏只查詢一張表,因此只顯示book。
type:指定本數據表和其餘數據表之間的關聯關係,該表中全部符合檢索值的記錄都會被取出來和從上一個表中取出來的記錄做聯合。
ref用於鏈接程序使用鍵的最左前綴或者是該鍵不是 primary key 或 unique索引(換句話說,就是鏈接程序沒法根據鍵值只取得一條記錄)的狀況。當根據鍵值只查詢到少數幾條匹配的記錄時,這就是一個不錯的鏈接類型。(注意,我的這裏不是很理解,百度了不少資料,全是大白話,等之後用到了這類信息時,在回過頭來補充,這裏不懂對後面的影響不大。)可能的取值有 system、const、eq_ref、index和All。
possible_keys:MySQL在搜索數據記錄時能夠選用的各個索引。目前表裏有兩個索引一個是主鍵一個是anthor。由於目前表裏沒有數據,因此主鍵索引未被使用。
key:實際選用的索引。
key_len:顯示了mysql使用索引的長度(也就是使用的索引個數),當 key 字段的值爲 null時,索引的長度就是 null。注意,key_len的值能夠告訴你在聯合索引中mysql會真正使用了哪些索引。
ref:給出關聯關係中另外一個數據表中數據列的名字。常量(const),這裏使用的是'nana',就是常量。
rows:MySQL在執行這個查詢時預計會從這個數據表裏讀出的數據行的個數。
extra:提供了與關聯操做有關的信息,沒有則什麼都不寫。
上面的一大堆東西能看懂多少看多少,咱們最主要的是看 possible_keys 和 key 這兩個屬性,上面顯示了key爲anthor。說明使用了索引。
二、建立惟一索引:
## 建立惟一索引
CREATE TABLE tab1( id INT(5) NOT NULL, name CHAR(20) NOT NULL, UNIQUE INDEX uniqId(id) );
## 查看錶的建立
SHOW CREATE TABLE tab1; ---------------------------------結果-------------------------------- CREATE TABLE `tab1` ( `id` int(5) NOT NULL, `name` char(20) NOT NULL, UNIQUE KEY `uniqId` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
## 查看索引使用信息
EXPLAIN SELECT * FROM tab1 WHERE id = 1;
---------------------------------結果--------------------------------
EXPLAIN SELECT * FROM tab1 WHERE id = 2;
---------------------------------結果--------------------------------
能夠看到,經過id查詢時,會使用惟一索引。而且還實驗了查詢一個沒有的id值,則不會使用索引,我以爲緣由是全部的id應該會存儲到一個const tables中,若是沒有該id值,那麼就沒有查找的必要了。
三、建立主鍵索引:
## 建立主鍵索引
CREATE TABLE tab2( id INT(4) NOT NULL, name char(20) DEFAULT NULL, PRIMARY KEY(id));
## 查看錶的建立
SHOW CREATE TABLE tab2; ---------------------------------結果-------------------------------- CREATE TABLE `tab2` ( `id` int(4) NOT NULL, `name` char(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
## 插入數據,查看下索引的使用,否則沒有id的值索引不會被使用
INSERT INTO tab2 VALUES(1,'nana');
## 查看索引使用信息
EXPLAIN SELECT * FROM tab2 WHERE id = 1;
---------------------------------結果--------------------------------
四、建立組合索引:
## 建立組合索引
CREATE TABLE tab3( id INT(4) NOT NULL, name CHAR(20) NOT NULL, age INT(3) NOT NULL, info VARCHAR(255), INDEX multiIdx(id,name,age) );
## 查看錶的建立
SHOW CREATE TABLE tab3; ---------------------------------結果-------------------------------- CREATE TABLE `tab3` ( `id` int(4) NOT NULL, `name` char(20) NOT NULL, `age` int(3) NOT NULL, `info` varchar(255) DEFAULT NULL, KEY `multiIdx` (`id`,`name`,`age`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
## 查看索引使用信息
EXPLAIN SELECT * FROM tab3 WHERE id = 1 AND name = 'nana';
---------------------------------結果--------------------------------
EXPLAIN SELECT * FROM tab3 WHERE age = 3 AND name = 'nana';
---------------------------------結果--------------------------------
最左前綴:組合索引聽從了最左前綴,利用索引中最左邊的列集來匹配行,這樣的列集稱爲最左前綴。例如,這裏由id、name和age3個字段構成的索引,索引行中就按id/name/age的順序存放,索引組合中的字段能夠是(id,name,age)、(id,name)或者(id)。若是要查詢的字段不構成最左面的前綴原則,那麼就不會用索引,好比,age或者(name,age)組合就不會使用索引查詢。
四、建立全文索引:
## 建立全文索引,支持的字段類型爲CHAR、VARCHAR和TEXT,存儲引擎爲MyISAM
CREATE TABLE tab4( id INT(4) NOT NULL, name CHAR(20) NOT NULL, age INT(3) NOT NULL, info VARCHAR(255), FULLTEXT INDEX fullTxtIdx(info) )ENGINE=MyISAM;
## 查看錶的建立
SHOW CREATE TABLE tab4; ---------------------------------結果-------------------------------- CREATE TABLE `tab4` ( `id` int(4) NOT NULL, `name` char(20) NOT NULL, `age` int(3) NOT NULL, `info` varchar(255) DEFAULT NULL, FULLTEXT KEY `fullTxtIdx` (`info`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
## 插入數據,查看下索引的使用
INSERT INTO tab4 VALUES(1,'AAA',3,'text is so good,hei,my name is black'),(2,'BBB',4,'my name is white');
## 全文搜索
## 未找到結果,不知道爲何
SELECT * FROM tab4 WHERE MATCH(info) AGAINST('white');
## 查看索引使用信息
EXPLAIN SELECT * FROM tab4 WHERE MATCH(info) AGAINST('white');
---------------------------------結果--------------------------------
五、建立空間索引:
## 建立空間索引
CREATE TABLE tab5( geo GEOMETRY NOT NULL, SPATIAL INDEX spatIdx(geo) )ENGINE=MyISAM;
## 查看錶的建立
SHOW CREATE TABLE tab5; ---------------------------------結果-------------------------------- CREATE TABLE `tab5` ( `geo` geometry NOT NULL, SPATIAL KEY `spatIdx` (`geo`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
Ⅱ、在建立表後建立索引:
## 在已經存在的表上建立索引
ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名] (索引字段名(長度))
## 查看錶的索引
SHOW INDEX FROM book;
---------------------------------結果--------------------------------
Table:建立索引的表。
Non_unique:表示索引是否惟一,其中1表明:非惟一索引, 0表明:惟一索引。
Key_name:索引名稱。
Seq_in_index:表示該字段在索引中的位置,單列索引該值爲1,組合索引爲每一個字段在索引定義中的順序(這個只須要知道單列索引該值爲1,組合索引爲別的)。
Column_name:表示定義索引的列字段。
Sub_part:表示索引的長度,當字段值爲null時,索引長度爲null。
Null:表示該字段是否能爲空值。
Index_type:表示索引類型。
## 爲表添加索引
ALTER TABLE book ADD INDEX BkNameIdx(name(30));
## 查看錶的索引
SHOW INDEX FROM book;
---------------------------------結果--------------------------------
## 使用CREATE INDEX建立索引
CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] 索引名稱 ON 表名(建立索引的字段名[length])
## 爲book表增長一個普通索引info。字段爲CHAR,VARCHAR類型時,索引length能夠小於字段實際長度;若是是BLOB和TEXT類型,必須指定 length
CREATE INDEX BkInfoIdx ON book(info(10));
## 查看錶的索引
SHOW INDEX FROM book;
---------------------------------結果--------------------------------
Ⅲ、刪除索引:
## 使用ALTER DROP刪除索引
ALTER TABLE 表名 DROP INDEX 索引名
## 刪除book表中的名稱爲BkInfoIdx的索引
ALTER TABLE book DROP INDEX BkInfoIdx;
## 查看錶的索引
SHOW INDEX FROM book;
---------------------------------結果--------------------------------
## 使用DROP INDEX刪除索引
DROP INDEX 索引名 ON 表名;
## 刪除book表中的名稱爲BkNameIdx的索引
DROP INDEX BkNameIdx ON book;
## 查看錶的索引
SHOW INDEX FROM book;
---------------------------------結果--------------------------------
MySQL的索引到這裏差很少就講完了,總結一下咱們到目前爲止應該知道哪些東西
一、索引是幹嗎的?爲何要有索引?
這個很重要,須要本身理解一下,不懂能夠多看幾遍索引介紹。
二、索引的分類:單列索引(普通索引、惟一索引和主鍵索引)、組合索引、全文索引和空間索引。
三、索引的使用:
給表中建立索引,添加索引,刪除索引。