|
索引: 索引是一種提高查詢效率的數(shù)據(jù)結(jié)構(gòu)(B樹或者是哈希結(jié)構(gòu));索引是創(chuàng)建在數(shù)據(jù)庫(kù)表中,是對(duì)數(shù)據(jù)庫(kù)表中的一列或者多列的值進(jìn)行排序的一個(gè)結(jié)果,好處就是提高查詢效率; 一般情況下,一次查詢只用一個(gè)索引; 索引的分類:
索引的創(chuàng)建和刪除的SQL語句: (一)索引的創(chuàng)建 在創(chuàng)建表的時(shí)候指定索引 create table table_name( id int, name varchar(20), index(id) ); 在已經(jīng)創(chuàng)建好的表上添加索引 create [unique|fulltext|spatial] index idx_id(索引名) on 表名(id屬性名);alter table 表名 add [unique|fulltext|spatial] index index_name; //第二種方法 (二)索引的刪除 drop index index_name(索引名) on 表名 索引執(zhí)行過程分析: 使用explain關(guān)鍵分析查詢SQL explain select * from Student where Sname like 'zhaolei'\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: Student type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4 Extra: Using where possible_keys:表示SQL執(zhí)行可能會(huì)命中的索引有哪些; key:表示執(zhí)行過程真正使用的索引名稱 rows:表示查詢影響的數(shù)據(jù)行數(shù) 當(dāng)前查詢possible_keys\key都為null,則未命中索引 rows=4表示當(dāng)前查詢操作對(duì)每一行數(shù)據(jù)都進(jìn)行比較 添加索引后,分析執(zhí)行過程 explain select * from Student where Sname like 'zhaolei'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: Student type: range possible_keys: idx_name key: idx_name key_len: 27 ref: NULL rows: 1 Extra: Using index condition 1 row in set (0.01 sec)通過explain關(guān)鍵分析查詢SQL,可以看出當(dāng)前查詢命中索引idx_name, rows: 1表示通過一條記錄就查詢到了結(jié)果 索引的底層原理 mysql支持兩種索引,一種是B樹索引,一種是哈希表索引; 問:數(shù)據(jù)庫(kù)中常見的慢查詢的優(yōu)化方式是什么? 答:加索引; 問:?jiǎn)柺裁醇铀饕梢詢?yōu)化查詢? 答:因?yàn)槟軠p少磁盤IO; 問:怎么減少磁盤IO的? 答:索引是一種優(yōu)化查詢的數(shù)據(jù)結(jié)構(gòu),比如在MySQL中用到的B+樹,這種數(shù)據(jù)結(jié)構(gòu)是可以優(yōu)化查詢的,所以我們可以利用索引來快速的查找數(shù)據(jù); 問:那你知道哪些數(shù)據(jù)結(jié)構(gòu)可以提高查詢速度嗎? 答:紅黑樹,二叉樹,哈希表,B樹(B-樹),B+樹等; 問:那為什么MySQL使用B+樹呢? 答:如下: MYSQL InnoDB存儲(chǔ)引擎,基于B-樹(實(shí)際MYSQL采用的是B+樹)的索引結(jié)構(gòu)。B-樹是一種m階平衡樹,葉子節(jié)點(diǎn)都在同一層,由于每一個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)量比較大,所以整個(gè)B-樹的層數(shù)是非常低的,基本上不超過三層; 由于磁盤的讀取也是按block塊操作的(內(nèi)存是按page頁(yè)面操作的),因此B-樹的節(jié)點(diǎn)大小一般設(shè)置為和磁盤塊大小一致,這樣一個(gè)B-樹節(jié)點(diǎn),就可以通過一次磁盤I/O把一個(gè)磁盤塊的數(shù)據(jù)全部存儲(chǔ)下來,所以當(dāng)使用B-樹存儲(chǔ)索引的時(shí)候,磁盤I/O的操作次數(shù)是最少的(MySQL的讀寫效率,主要集中在磁盤I/O上)。 那么MySQL最終為什么要采用B+樹存儲(chǔ)索引結(jié)構(gòu)呢,那么看看B-樹和B+樹在存儲(chǔ)結(jié)構(gòu)上有什么不同?
哈希索引當(dāng)然是由哈希表實(shí)現(xiàn)的,哈希表對(duì)數(shù)據(jù)并不排序,因此不適合做區(qū)間查找,效率非常低,需要搜索整個(gè)哈希表結(jié)構(gòu)。 MySQL數(shù)據(jù)庫(kù)的存儲(chǔ)引擎MyISAM和InNoDB的索引結(jié)構(gòu) 聚集索引和非聚集索引:聚集就是索引和數(shù)據(jù)存放在一個(gè)文件里面,非聚集索引就是索引和數(shù)據(jù)分別存放在兩個(gè)文件里面; MyISAM存儲(chǔ)引擎(非聚集索引) MyISAM引擎使用B+樹作為索引結(jié)構(gòu)、葉節(jié)點(diǎn)的數(shù)據(jù)域存放的是數(shù)據(jù)地址,在MyISAM引擎中,主索引和輔助索引在結(jié)構(gòu)上沒有任何區(qū)別,只是主索引要求key是唯一的,而輔助索引的key可以重復(fù),如果給其他字段創(chuàng)建輔助索引,結(jié)構(gòu)圖如下: 根據(jù)上面兩張圖,首先按照B+樹搜索算法搜索索引,如果指定的key存在,則取出其數(shù)據(jù)域的值,然后以數(shù)據(jù)域的值為地址,讀取相應(yīng)的數(shù)據(jù)記錄; InNoDB存儲(chǔ)引擎(聚集索引) InNoDB存儲(chǔ)引擎的主鍵索引,葉子節(jié)點(diǎn)中,索引關(guān)鍵字和數(shù)據(jù)是在一起存放的,如圖: 可以看到,索引關(guān)鍵字和數(shù)據(jù)存儲(chǔ)在葉子節(jié)點(diǎn)中; InNoDB輔助索引,葉子節(jié)點(diǎn)存放的是索引關(guān)鍵字和對(duì)應(yīng)的主鍵(為了一致性和節(jié)省存儲(chǔ)空間): 輔助索引的B+樹,先根據(jù)關(guān)鍵字找到對(duì)應(yīng)的主鍵,再去主鍵索引樹上找到對(duì)應(yīng)的行記錄數(shù)據(jù),從索引樹上可以看到,InNoDB的索引關(guān)鍵字和數(shù)據(jù)都是在一起存放的,體現(xiàn)在磁盤存儲(chǔ)上,例如創(chuàng)建一個(gè)user表,在磁盤上只存儲(chǔ)兩種結(jié)構(gòu),user.frm(存儲(chǔ)表的結(jié)構(gòu)),user.idb(存儲(chǔ)索引和數(shù)據(jù)); 聯(lián)合索引 就是先根據(jù)第一個(gè)鍵排序,第一個(gè)鍵相同的話,按第二個(gè)鍵排序…… 索引的優(yōu)化
總結(jié)下索引的優(yōu)化:
SELECT * FROMhoudunwangWHEREunameLIKE'后盾%' -- 走索引 SELECT * FROMhoudunwangWHEREunameLIKE '%后盾%' -- 不走索引
CREATE TABLEa(achar(10)); EXPLAIN SELECT * FROMaWHEREa='1' – 走索引 EXPLAIN SELECT * FROM a WHERE a=1 – 不走索引
|
|
|