普通索引和唯一索引的選擇
業(yè)務(wù)場(chǎng)景一:是否將唯一字段設(shè)置為主鍵索引
數(shù)據(jù)中出現(xiàn)了一個(gè)字段保證是唯一的,是否高設(shè)計(jì)這個(gè)字段為主鍵呢?建議不使用,應(yīng)該創(chuàng)建一個(gè)遞增的唯一索引。原因是在innodb中主鍵索引文件和數(shù)據(jù)文件是同一個(gè),利用遞增主鍵生成的索引樹占用內(nèi)存小,主要表現(xiàn)在,自增主鍵自身就小,還有就是自增主鍵是遞增的,生成的索引樹是緊湊的,而唯一字段相對(duì)更大,并且是隨機(jī)的,生成索引樹會(huì)造成也的分裂或者合并情況多。
業(yè)務(wù)場(chǎng)景二:普通索引和唯一索引怎么選擇
分析:
- 查詢分析。對(duì)于唯一索引,當(dāng)我們查找到第一個(gè)滿足的時(shí)候就會(huì)返回,對(duì)于普通索引查找到第一個(gè)滿足的情況還需要向下查找,直到查找到不滿足為止。這兩只之間的差距真的大嗎?其實(shí)不然,因?yàn)閿?shù)據(jù)的讀取不是按行來(lái)讀取的,而是會(huì)讀取一頁(yè)的數(shù)據(jù),假如所有慢點(diǎn)的數(shù)據(jù)都在同一頁(yè),那么這兩者之間的差距微乎其微,但是如果是普通索引,可能會(huì)造成需要多一次磁盤IO的情況,不過(guò)我覺(jué)得概率也是很低的。
- 操作分析。在普通索引中,有一個(gè)change buffer 。這個(gè)change buffer是用來(lái)干什么的呢?change buffer是為了減少磁盤的查詢IO的。那為什么唯一索引沒(méi)有呢,因?yàn)槲ㄒ凰饕俏ㄒ坏模檎业臄?shù)據(jù)必須是在內(nèi)存中,change buffer無(wú)法作用。所以,先得出結(jié)論,使用普通索引可能可以減少磁盤IO,而磁盤IO是數(shù)據(jù)庫(kù)最昂貴的操作。
change buffer的用途
既然change buffer是作用于普通索引,那么我們就來(lái)分析一下其對(duì)于普通索引的作用體現(xiàn)在哪里。
- insert/delete,當(dāng)插入的時(shí)候,假如數(shù)據(jù)在內(nèi)存中,則直接插入內(nèi)存中,記錄redo log。假如數(shù)據(jù)也不在內(nèi)存中,不需要讀取磁盤,在change buffer中記錄下來(lái)插入記錄,記錄插入信息,記錄在change buffer 中插入信息。這兩條記錄記錄在redo log中。
- update操作,假如數(shù)據(jù)也在內(nèi)存中,則直接修改,否則也是記錄在change buffer 中。
那么change buffer 中的記錄什么時(shí)候更新呢?當(dāng)下一次的查詢操作讀取到數(shù)據(jù)頁(yè)是,將會(huì)先執(zhí)行change buffer中的操作。
綜上,可以看出change buffe減少了磁盤IO操作。
宕機(jī)之后,change buffer中的數(shù)據(jù)不會(huì)丟失嗎?
其實(shí)change buffer中的數(shù)據(jù)也會(huì)保存在文件中,之后做merge操作,merge操作怎么進(jìn)行呢?首先從磁盤中讀取數(shù)據(jù),然后將change buffer中的操作進(jìn)行,可能是多個(gè)操作,之后再記錄redo log記錄chang buffer和數(shù)據(jù)的變更,此時(shí)內(nèi)存中的數(shù)據(jù)是最新的,但是磁盤中的數(shù)據(jù)還未更新,需要刷回磁盤。前面也提到了,在進(jìn)行操作的時(shí)候會(huì)記錄redo log,所以chang buffer的操作也是被記錄的,數(shù)據(jù)不會(huì)丟失。