轉載自:https://www.cnblogs.com/jiawen010/p/11805241.html
要看原版請?zhí)D到上面的網址。
總結:InnoDB中谎亩,表數據文件本身就是按B+Tree組織的一個索引結構驯绎,聚簇索引就是按照每張表的主鍵構造一顆B+樹垒酬,同時葉子節(jié)點中存放的就是整張表的行記錄數據柑潦,也將聚集索引的葉子節(jié)點稱為數據頁。這個特性決定了索引組織表中數據也是索引的一部分锈遥;
一般建表會用一個自增主鍵做聚簇索引误算,沒有的話MySQL會默認創(chuàng)建,但是這個主鍵如果更改代價較高迷殿,故建表時要考慮自增ID不能頻繁update這點儿礼。
我們日常工作中,根據實際情況自行添加的索引都是輔助索引庆寺,輔助索引就是一個為了需找主鍵索引的二級索引蚊夫,現在找到主鍵索引再通過主鍵索引找數據;
本文鏈接:https://blog.csdn.net/lm1060891265/article/details/81482136
參考博客:http://www.admin10000.com/document/5372.html
聚簇索引并不是一種單獨的索引類型懦尝,而是一種數據存儲方式知纷。具體細節(jié)依賴于其實現方式。
MySQL數據庫中innodb存儲引擎陵霉,B+樹索引可以分為聚簇索引(也稱聚集索引琅轧,clustered index)和輔助索引(有時也稱非聚簇索引或二級索引,secondary index踊挠,non-clustered index)乍桂。這兩種索引內部都是B+樹,聚集索引的葉子節(jié)點存放著一整行的數據效床。
Innobd中的主鍵索引是一種聚簇索引睹酌,非聚簇索引都是輔助索引,像復合索引剩檀、前綴索引憋沿、唯一索引。
Innodb使用的是聚簇索引沪猴,MyISam使用的是非聚簇索引
聚簇索引(聚集索引)
聚簇索引就是按照每張表的主鍵構造一顆B+樹辐啄,同時葉子節(jié)點中存放的就是整張表的行記錄數據,也將聚集索引的葉子節(jié)點稱為數據頁运嗜。這個特性決定了索引組織表中數據也是索引的一部分壶辜,每張表只能擁有一個聚簇索引。
Innodb通過主鍵聚集數據洗出,如果沒有定義主鍵士复,innodb會選擇非空的唯一索引代替图谷。如果沒有這樣的索引翩活,innodb會隱式的定義一個主鍵來作為聚簇索引阱洪。
聚簇索引的優(yōu)缺點
優(yōu)點:
1.數據訪問更快,因為聚簇索引將索引和數據保存在同一個B+樹中菠镇,因此從聚簇索引中獲取數據比非聚簇索引更快
2.聚簇索引對于主鍵的排序查找和范圍查找速度非橙咻快
缺點:
1.插入速度嚴重依賴于插入順序,按照主鍵的順序插入是最快的方式利耍,否則將會出現頁分裂蚌本,嚴重影響性能。因此隘梨,對于InnoDB表程癌,我們一般都會定義一個自增的ID列為主鍵
2.更新主鍵的代價很高,因為將會導致被更新的行移動轴猎。因此嵌莉,對于InnoDB表,我們一般定義主鍵為不可更新捻脖。
3.二級索引訪問需要兩次索引查找锐峭,第一次找到主鍵值,第二次根據主鍵值找到行數據可婶。
輔助索引(非聚簇索引)
在聚簇索引之上創(chuàng)建的索引稱之為輔助索引沿癞,輔助索引訪問數據總是需要二次查找。輔助索引葉子節(jié)點存儲的不再是行的物理位置矛渴,而是主鍵值椎扬。通過輔助索引首先找到的是主鍵值,再通過主鍵值找到數據行的數據頁具温,再通過數據頁中的Page Directory找到數據行盗舰。
Innodb輔助索引的葉子節(jié)點并不包含行記錄的全部數據,葉子節(jié)點除了包含鍵值外桂躏,還包含了相應行數據的聚簇索引鍵钻趋。
輔助索引的存在不影響數據在聚簇索引中的組織,所以一張表可以有多個輔助索引剂习。在innodb中有時也稱輔助索引為二級索引蛮位。
Innodb聚簇索引和MyIsam非聚簇索引的比較說明
參考博客:https://www.cnblogs.com/zlcxbb/p/5757245.html
InnoDB索引實現
InnoDB也使用B+Tree作為索引結構,但具體實現方式卻與MyISAM截然不同.
1)主鍵索引:
MyISAM索引文件和數據文件是分離的鳞绕,索引文件僅保存數據記錄的地址失仁。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構们何,這棵樹的葉節(jié)點data域保存了完整的數據記錄萄焦。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。
(圖inndb主鍵索引)是InnoDB主索引(同時也是數據文件)的示意圖拂封,可以看到葉節(jié)點包含了完整的數據記錄茬射。這種索引叫做聚集索引。因為InnoDB的數據文件本身要按主鍵聚集冒签,所以InnoDB要求表必須有主鍵(MyISAM可以沒有)在抛,如果沒有顯式指定,則MySQL系統(tǒng)會自動選擇一個可以唯一標識數據記錄的列作為主鍵萧恕,如果不存在這種列刚梭,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節(jié)票唆,類型為長整形朴读。
2)InnoDB的輔助索引
???InnoDB的所有輔助索引都引用主鍵作為data域。例如走趋,下圖為定義在Col3上的一個輔助索引:
InnoDB 表是基于聚簇索引建立的磨德。因此InnoDB 的索引能提供一種非常快速的主鍵查找性能吆视。不過典挑,它的輔助索引(Secondary Index, 也就是非主鍵索引)也會包含主鍵列啦吧,所以您觉,如果主鍵定義的比較大,其他索引也將很大授滓。如果想在表上定義 琳水、很多索引,則爭取盡量把主鍵定義得小一些般堆。InnoDB 不會壓縮索引在孝。
文字符的ASCII碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜索十分高效淮摔,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵私沮,然后用主鍵到主索引中檢索獲得記錄。
不同存儲引擎的索引實現方式對于正確使用和優(yōu)化索引都非常有幫助和橙,例如知道了InnoDB的索引實現后仔燕,就很容易明白:
1、為什么不建議使用過長的字段作為主鍵魔招,因為所有輔助索引都引用主索引晰搀,過長的主索引會令輔助索引變得過大。再例如办斑,
2外恕、用非單調的字段作為主鍵在InnoDB中不是個好主意,因為InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整鳞疲,十分低效罪郊,而使用自增字段作為主鍵則是一個很好的選擇。
InnoDB使用的是聚簇索引建丧,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節(jié)點上波势,若使用"where id = 14"這樣的條件查找主鍵翎朱,則按照B+樹的檢索算法即可查找到對應的葉節(jié)點,之后獲得行數據尺铣。若對Name列進行條件搜索拴曲,則需要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節(jié)點獲取對應的主鍵凛忿。第二步使用主鍵在主索引B+樹種再執(zhí)行一次B+樹檢索操作澈灼,最終到達葉子節(jié)點即可獲取整行數據。
MyISAM索引實現
MyISAM索引文件和數據文件是分離的店溢,索引文件僅保存數據記錄的地址
1)主鍵索引:
MyISAM引擎使用B+Tree作為索引結構叁熔,葉節(jié)點的data域存放的是數據記錄的地址。下圖是MyISAM主鍵索引的原理圖:
這里設表一共有三列床牧,假設我們以Col1為主鍵荣回,圖myisam1是一個MyISAM表的主索引(Primary key)示意「昕龋可以看出MyISAM的索引文件僅僅保存數據記錄的地址心软。
2)輔助索引(Secondary key)
在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區(qū)別著蛙,只是主索引要求key是唯一的删铃,而輔助索引的key可以重復。如果我們在Col2上建立一個輔助索引踏堡,則此索引的結構如下圖所示:
同樣也是一顆B+Tree猎唁,data域保存數據記錄的地址。因此顷蟆,MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引胖秒,如果指定的Key存在,則取出其data域的值慕的,然后以data域的值為地址阎肝,讀取相應數據記錄。
MyISAM的索引方式也叫做“非聚集”的肮街,之所以這么稱呼是為了與InnoDB的聚集索引區(qū)分风题。
MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什么不同,節(jié)點的結構完全一致只是存儲的內容不同而已沛硅,主鍵索引B+樹的節(jié)點存儲了主鍵眼刃,輔助鍵索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方摇肌,這兩顆B+樹的葉子節(jié)點都使用一個地址指向真正的表數據擂红,對于表數據來說,這兩個鍵沒有任何差別围小。由于索引樹是獨立的昵骤,通過輔助鍵檢索無需訪問主鍵的索引樹。
為了更形象說明這兩種索引的區(qū)別肯适,我們假想一個表如下圖存儲了4行數據变秦。其中Id作為主索引,Name作為輔助索引框舔。圖示清晰的顯示了聚簇索引和非聚簇索引的差異蹦玫。
問題:主鍵索引是聚集索引還是非聚集索引?
在Innodb下主鍵索引是聚集索引刘绣,在Myisam下主鍵索引是非聚集索引
聚簇索引和非聚簇索引的區(qū)別
聚簇索引的葉子節(jié)點存放的是主鍵值和數據行樱溉,支持覆蓋索引;二級索引的葉子節(jié)點存放的是主鍵值或指向數據行的指針纬凤。
由于節(jié)子節(jié)點(數據頁)只能按照一顆B+樹排序饺窿,故一張表只能有一個聚簇索引。輔助索引的存在不影響聚簇索引中數據的組織移斩,所以一張表可以有多個輔助索引
注:?覆蓋索引(covering index)指一個查詢語句的執(zhí)行只用從索引中就能夠取得肚医,不必從數據表中讀取。也可以稱之為實現了索引覆蓋向瓷。 當一條查詢語句符合覆蓋索引條件時肠套,MySQL只需要通過索引就可以返回查詢所需要的數據,這樣避免了查到索引后再返回表操作猖任,減少I/O提高效率你稚。 如,表covering_index_sample中有一個普通索引 idx_key1_key2(key1,key2)朱躺。當我們通過SQL語句:select key2 from covering_index_sample where key1 = ‘keytest’;的時候刁赖,就可以通過覆蓋索引查詢,無需回表长搀。