马士兵mysql_MYSQL相关总结(马士兵教育)
MySQL的邏輯結(jié)構(gòu)
客戶端+服務(wù)器+存儲(chǔ)引擎
存儲(chǔ)引擎
查看存儲(chǔ)引擎: show engines.我的電腦里默認(rèn)的是InnoDB;
InnoDB和MyISAM索引采用的是B+樹(shù), MEMORY采用的是Hash索引.
MySql中最常用的的存儲(chǔ)引擎是InnoDB和MyISAM.
前者在磁盤(pán)中會(huì)落2個(gè)文件,分別是.frm和.ibd..frm代表form files,代表格式文件..ibd中包含真實(shí)數(shù)據(jù)和索引數(shù)據(jù).
而myISAM中會(huì)落3個(gè)文件,分別是.frm,.MYD和.MYI,其中后面兩種格式代表真實(shí)數(shù)據(jù)和索引數(shù)據(jù).
內(nèi)存和磁盤(pán)交互:
磁盤(pán)預(yù)讀:預(yù)讀的長(zhǎng)度一般是頁(yè)的整數(shù)倍.頁(yè)是存儲(chǔ)器(包括內(nèi)存和磁盤(pán))的邏輯塊,通常為4KB,內(nèi)存和磁盤(pán)以頁(yè)來(lái)為單位交換數(shù)據(jù).InnoDB默認(rèn)一次預(yù)讀16KB的數(shù)據(jù).
索引:
為什么要?jiǎng)?chuàng)建索引:
如果沒(méi)有索引,查找數(shù)據(jù)是全表掃描,而如果有索引的話,會(huì)按照B+樹(shù)的結(jié)構(gòu)去查找數(shù)據(jù).
創(chuàng)建索引是個(gè)什么過(guò)程?
就是把數(shù)據(jù)組織成數(shù)據(jù)結(jié)構(gòu)的過(guò)程.
存儲(chǔ)在文件系統(tǒng)中,存儲(chǔ)形式和存儲(chǔ)引擎有關(guān),索引文件的結(jié)構(gòu)包括hash,二叉樹(shù),B樹(shù)和B+樹(shù).
hash表:是數(shù)組+鏈表的結(jié)構(gòu).
hash作為索引存在的問(wèn)題 :
1.哈希函數(shù)不容易選擇
2.hash存儲(chǔ)需要將所有的數(shù)據(jù)文件添加到內(nèi)存(why?待后知后覺(jué)),浪費(fèi)內(nèi)存空間.
3.等值查詢用hash比較快,但是實(shí)際中范圍查詢更多,hash不太合適.
以上問(wèn)題使得hash沒(méi)有作為大部分存儲(chǔ)引擎(查找數(shù)據(jù)是與磁盤(pán)進(jìn)行交互)的數(shù)據(jù)結(jié)構(gòu).而MEMORY存儲(chǔ)引擎是在內(nèi)存中進(jìn)行的,使用它的時(shí)候就接受它占內(nèi)存的問(wèn)題了,另外在內(nèi)存中查找速度很快.
二叉樹(shù),紅黑樹(shù)存在的問(wèn)題:
樹(shù)中元素存儲(chǔ)的是數(shù)據(jù)值,樹(shù)在物理結(jié)構(gòu)上是數(shù)組進(jìn)行存放的,可能邏輯結(jié)構(gòu)上很近的數(shù)據(jù)(比如父子)在物理結(jié)構(gòu)上會(huì)相差很遠(yuǎn)(比如當(dāng)樹(shù)很大時(shí)).因此,每次讀取磁盤(pán)頁(yè)的數(shù)據(jù)很多是用不上的.可能需要進(jìn)行很多次的IO交互才能夠找到要找的數(shù)據(jù).
都會(huì)因?yàn)闃?shù)的深度太深而造成io次數(shù)變多(指的是內(nèi)存和磁盤(pán)交互的次數(shù)),影響讀取的效率.
提升IO效率的兩個(gè)方法:
1.減少I(mǎi)O的次數(shù)
2.減少I(mǎi)O的大小
eg:不推薦使用select(*)的原因,是因?yàn)樗鼤?huì)把磁盤(pán)中全表的數(shù)據(jù)都拉到內(nèi)存(mysql的服務(wù))中,然后在內(nèi)存中去進(jìn)行篩選,篩選完畢后給到客戶端中.
B樹(shù):
樹(shù)中節(jié)點(diǎn)存儲(chǔ)的是數(shù)據(jù)塊.
圖中紫色的代表鍵值,它可能是記錄的主鍵.
樹(shù)的階數(shù)(degree)等于它可以最多存儲(chǔ)指針的個(gè)數(shù)(數(shù)據(jù)的個(gè)數(shù)比指針個(gè)數(shù)少1).
比如下面的這個(gè)示意圖,它最多能夠存3個(gè)指針,兩個(gè)data,它的degree是3.
假如當(dāng)前磁盤(pán)塊的大小為16KB,每個(gè)data占1KB的內(nèi)存,忽略鍵值和指針,一個(gè)磁盤(pán)塊中可以存16個(gè)data,即階為17.那么三層樹(shù)可以存儲(chǔ)的數(shù)據(jù)量16+17*16+17*17*16=16*(1+17+17*17)=4912條數(shù)據(jù).從這里可以看出來(lái)影響存儲(chǔ)數(shù)據(jù)多少的因素是data的大小,而這個(gè)時(shí)候B+樹(shù)就比較合適了.
B+樹(shù):
同樣的3層樹(shù),如果前兩層只存儲(chǔ)鍵值和指針的話,那么對(duì)應(yīng)存儲(chǔ)的指針數(shù)就會(huì)大大增加,假如前兩層每個(gè)磁盤(pán)可以存儲(chǔ)1600個(gè)指針,第三層仍然是存儲(chǔ)16個(gè)數(shù)據(jù),那么三層樹(shù)總共可以存儲(chǔ)的數(shù)據(jù)量=1600*1600*16 = 40960000,差不多數(shù)據(jù)容量增加了1萬(wàn)倍.
注意這里為什么特別在意樹(shù)的層數(shù)呢?因?yàn)闃?shù)的層數(shù)越深,查找樹(shù)的次數(shù)就越多(最壞情況,單枝退化成了鏈表).
B+樹(shù)中有兩種查找方式:一種是對(duì)于主鍵的范圍查找和分頁(yè)查找,另一種是從根節(jié)點(diǎn)開(kāi)始,進(jìn)行隨機(jī)查找.
InnoDB和MyISAM所以創(chuàng)建的區(qū)別:
InnoDB,葉子節(jié)點(diǎn)中放置的是數(shù)據(jù),對(duì)應(yīng).ibd, 聚簇/聚集索引.
注意:
1.InnoDB對(duì)主鍵創(chuàng)建索引,也就是把主鍵作為B+樹(shù)中的Key,如果沒(méi)有主鍵,會(huì)選擇唯一鍵,如果沒(méi)有唯一鍵,會(huì)生成一個(gè)6字節(jié)的row_id(不可見(jiàn))來(lái)作為主鍵(都是為了保證key的唯一性).
2.如果創(chuàng)建索引的鍵是其他字段,那么在葉子節(jié)點(diǎn)中存儲(chǔ)的是該記錄的主鍵,然后再通過(guò)主鍵索引找到對(duì)應(yīng)的記錄,這個(gè)過(guò)程叫做回表.
比如下圖中又對(duì)表中的name建立了索引(稱為二級(jí)索引/輔助索引),如果要執(zhí)行select * from table where name = "ma",根據(jù)"ma"找到了主鍵1,這個(gè)時(shí)候還需要根據(jù)主鍵回到表中查找所有的列.而如果select id from table where name = "ma"的話,則不會(huì)觸發(fā)回表.
MyISAM中葉子節(jié)點(diǎn)沖存儲(chǔ)的是地址,然后根據(jù)地址去查找數(shù)據(jù).所以存儲(chǔ)文件是.MYI,.MYD. 非聚簇索引.
MySQL的B+樹(shù)三層還是四層,取決于數(shù)據(jù)量的多少.
主鍵自增:
分布式不推薦(分布式中有自己的主鍵生成策略),
非分布式推薦.
主鍵自增,能夠保證后面插入的數(shù)據(jù)在建立索引時(shí)從添加到樹(shù)的結(jié)尾.如果主鍵是亂序的話,在創(chuàng)建索引時(shí),會(huì)插入到中間位置.如果中間位置滿了,會(huì)導(dǎo)致頁(yè)分裂,會(huì)造成維護(hù)上很麻煩.(添加到結(jié)尾,如果數(shù)據(jù)滿了也會(huì)造成頁(yè)分裂,但沒(méi)有中間插入的那種情況嚴(yán)重).
索引優(yōu)化相關(guān):
1.盡量用int來(lái)存儲(chǔ)索引,它只占4個(gè)字節(jié),而varchar會(huì)占用比較多的字節(jié).
2.
總結(jié)
以上是生活随笔為你收集整理的马士兵mysql_MYSQL相关总结(马士兵教育)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 可汗学院的数学从零开始学习顺序?
- 下一篇: MySQL之学生成绩表查询语句解析