Innodb引擎
Innodb引擎提供了對(duì)數(shù)據(jù)庫(kù)ACID事務(wù)的支持,并且實(shí)現(xiàn)了SQL標(biāo)準(zhǔn)的四種隔離級(jí)別,,關(guān)于數(shù)據(jù)庫(kù)事務(wù)與其隔離級(jí)別的內(nèi)容請(qǐng)見數(shù)據(jù)庫(kù)事務(wù)與其隔
離級(jí)別這篇文章,。該引擎還提供了行級(jí)鎖和外鍵約束,它的設(shè)計(jì)目標(biāo)是處理大容量數(shù)據(jù)庫(kù)系統(tǒng),,它本身其實(shí)就是基于MySQL后臺(tái)的完整數(shù)據(jù)庫(kù)系統(tǒng),,MySQL
運(yùn)行時(shí)Innodb會(huì)在內(nèi)存中建立緩沖池,用于緩沖數(shù)據(jù)和索引,。但是該引擎不支持FULLTEXT類型的索引,,而且它沒有保存表的行數(shù),當(dāng)SELECT
COUNT(*) FROM
TABLE時(shí)需要掃描全表,。當(dāng)需要使用數(shù)據(jù)庫(kù)事務(wù)時(shí),,該引擎當(dāng)然是首選。由于鎖的粒度更小,,寫操作不會(huì)鎖定全表,,所以在并發(fā)較高時(shí),使用Innodb引擎
會(huì)提升效率,。但是使用行級(jí)鎖也不是絕對(duì)的,,如果在執(zhí)行一個(gè)SQL語(yǔ)句時(shí)MySQL不能確定要掃描的范圍,InnoDB表同樣會(huì)鎖全表,。
MyIASM引擎
MyIASM是MySQL默認(rèn)的引擎,,但是它沒有提供對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持,也不支持行級(jí)鎖和外鍵,,因此當(dāng)INSERT(插入)或UPDATE(更
新)數(shù)據(jù)時(shí)即寫操作需要鎖定整個(gè)表,,效率便會(huì)低一些。不過(guò)和Innodb不同,,MyIASM中存儲(chǔ)了表的行數(shù),,于是SELECT COUNT(*)
FROM
TABLE時(shí)只需要直接讀取已經(jīng)保存好的值而不需要進(jìn)行全表掃描。如果表的讀操作遠(yuǎn)遠(yuǎn)多于寫操作且不需要數(shù)據(jù)庫(kù)事務(wù)的支持,,那么MyIASM也是很好的選
擇,。
兩種引擎的選擇
大尺寸的數(shù)據(jù)集趨向于選擇InnoDB引擎,因?yàn)樗С质聞?wù)處理和故障恢復(fù),。數(shù)據(jù)庫(kù)的大小決定了故障恢復(fù)的時(shí)間長(zhǎng)短,InnoDB可以利用事務(wù)日志
進(jìn)行數(shù)據(jù)恢復(fù),,這會(huì)比較快,。主鍵查詢?cè)贗nnoDB引擎下也會(huì)相當(dāng)快,,不過(guò)需要注意的是如果主鍵太長(zhǎng)也會(huì)導(dǎo)致性能問(wèn)題,關(guān)于這個(gè)問(wèn)題我會(huì)在下文中講到,。大
批的INSERT語(yǔ)句(在每個(gè)INSERT語(yǔ)句中寫入多行,,批量插入)在MyISAM下會(huì)快一些,但是UPDATE語(yǔ)句在InnoDB下則會(huì)更快一些,,尤
其是在并發(fā)量大的時(shí)候,。
Index——索引
索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。MyIASM和Innodb都使用了樹這種數(shù)據(jù)結(jié)構(gòu)做為索引,,關(guān)于樹我也曾經(jīng)寫過(guò)一篇文章樹是一種偉大的數(shù)據(jù)結(jié)構(gòu),,只是自己的理解,有興趣的朋友可以去閱讀,。下面我接著講這兩種引擎使用的索引結(jié)構(gòu),,講到這里,首先應(yīng)該談一下B-Tree和B+Tree,。
B-Tree和B+Tree
B+Tree是B-Tree的變種,,那么我就先講B-Tree吧,相信大家都知道紅黑樹,,這是我前段時(shí)間學(xué)《算法》一書時(shí),,實(shí)現(xiàn)的一顆紅黑樹,大家
可以參考,。其實(shí)紅黑樹類似2,3-查找樹,,這種樹既有2叉結(jié)點(diǎn)又有3叉結(jié)點(diǎn)。B-Tree也與之類似,,它的每個(gè)結(jié)點(diǎn)做多可以有d個(gè)分支(叉),,d稱為B-
Tree的度,如下圖所示,,它的每個(gè)結(jié)點(diǎn)可以有4個(gè)元素,,5個(gè)分支,于是它的度為5,。B-Tree中的元素是有序的,,比如圖中元素7左邊的指針指向的結(jié)點(diǎn)
中的元素都小于7,而元素7和16之間的指針指向的結(jié)點(diǎn)中的元素都處于7和16之間,,正是滿足這樣的關(guān)系,,才能高效的查找:首先從根節(jié)點(diǎn)進(jìn)行二分查找,找
到就返回對(duì)應(yīng)的值,,否則就進(jìn)入相應(yīng)的區(qū)間結(jié)點(diǎn)遞歸的查找,,直到找到對(duì)應(yīng)的元素或找到null指針,找到null指針則表示查找失敗。這個(gè)查找是十分高效
的,,其時(shí)間復(fù)雜度為O(logN)(以d為底,,當(dāng)d很大時(shí),樹的高度就很低),,因?yàn)槊看螜z索最多只需要檢索樹高h(yuǎn)個(gè)結(jié)點(diǎn),。
接下來(lái)就該講B+Tree了,它是B-Tree的變種,,如下面兩張圖所示:
vcHLx/i85LLp0a/Qp8LKoaM8L3A+DQo8aDMgaWQ9"myisam引擎的索引結(jié)構(gòu)">MyISAM引擎的索引結(jié)構(gòu)
MyISAM引擎的索引結(jié)構(gòu)為B+Tree,,其中B+Tree的數(shù)據(jù)域存儲(chǔ)的內(nèi)容為實(shí)際數(shù)據(jù)的地址,也就是說(shuō)它的索引和實(shí)際的數(shù)據(jù)是分開的,,只不過(guò)是用索引指向了實(shí)際的數(shù)據(jù),,這種索引就是所謂的非聚集索引。
Innodb引擎的索引結(jié)構(gòu)
MyISAM引擎的索引結(jié)構(gòu)同樣也是B+Tree,,但是Innodb的索引文件本身就是數(shù)據(jù)文件,,即B+Tree的數(shù)據(jù)域存儲(chǔ)的就是實(shí)際的數(shù)據(jù),這種索引就是聚集索引,。這個(gè)索引的key就是數(shù)據(jù)表的主鍵,,因此InnoDB表數(shù)據(jù)文件本身就是主索引。
因?yàn)镮nnoDB的數(shù)據(jù)文件本身要按主鍵聚集,,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),,如果沒有顯式指定,則MySQL系統(tǒng)會(huì)自動(dòng)選擇一個(gè)可以唯一標(biāo)識(shí)數(shù)據(jù)記錄的列作為主鍵,,如果不存在這種列,,則MySQL自動(dòng)為InnoDB表生成一個(gè)隱含字段作為主鍵,這個(gè)字段長(zhǎng)度為6個(gè)字節(jié),,類型為長(zhǎng)整形,。
并且和MyISAM不同,InnoDB的輔助索引數(shù)據(jù)域存儲(chǔ)的也是相應(yīng)記錄主鍵的值而不是地址,,所以當(dāng)以輔助索引查找時(shí),,會(huì)先根據(jù)輔助索引找到主
鍵,再根據(jù)主鍵索引找到實(shí)際的數(shù)據(jù),。所以Innodb不建議使用過(guò)長(zhǎng)的主鍵,,否則會(huì)使輔助索引變得過(guò)大。建議使用自增的字段作為主鍵,,這樣B+Tree的
每一個(gè)結(jié)點(diǎn)都會(huì)被順序的填滿,,而不會(huì)頻繁的分裂調(diào)整,會(huì)有效的提升插入數(shù)據(jù)的效率,。