聚簇索引并不是一種單獨(dú)的索引類型勒奇,而是一種數(shù)據(jù)存儲方式番川。比如闹炉,InnoDB的聚簇索引使用B+Tree的數(shù)據(jù)結(jié)構(gòu)存儲索引和數(shù)據(jù)诡必。
當(dāng)表有聚簇索引時(shí)奢方,它的數(shù)據(jù)行實(shí)際上存放在索引的葉子頁(leaf page)中。因?yàn)闊o法同時(shí)把數(shù)據(jù)行存放在兩個(gè)不同的地方爸舒,所以一個(gè)表只能有一個(gè)聚簇索引(不過蟋字,覆蓋索引可以模擬多個(gè)聚簇索引的情況)。
術(shù)語“聚簇”表示數(shù)據(jù)行和相鄰的鍵值緊湊地存儲在一起扭勉。
聚簇索引的二級索引:葉子節(jié)點(diǎn)不會保存引用的行的物理位置鹊奖,而是保存行的主鍵值。
對于聚簇索引的存儲引擎涂炎,數(shù)據(jù)的物理存放順序與索引順序是一致的忠聚,即:只要索引是相鄰的,那么對應(yīng)的數(shù)據(jù)一定也是相鄰地存放在磁盤上的唱捣,如果主鍵不是自增id两蟀,可以想象,它會干些什么震缭,不斷地調(diào)整數(shù)據(jù)的物理地址赂毯、分頁,當(dāng)然也有其他一些措施來減少這些操作,但卻無法徹底避免党涕。但烦感,如果是自增的,那就簡單了膛堤,它只需要一頁一頁地寫手趣,索引結(jié)構(gòu)相對緊湊,磁盤碎片少骑祟,效率也高回懦。
對于非聚簇索引的存儲引擎,表數(shù)據(jù)存儲順序與索引順序無關(guān)次企,葉結(jié)點(diǎn)包含索引字段值及指向數(shù)據(jù)頁數(shù)據(jù)行的邏輯指針怯晕,其行數(shù)量與數(shù)據(jù)表行數(shù)據(jù)量一致。
下圖1展示了聚簇索引的記錄是如何存放的缸棵。注意到舟茶,節(jié)點(diǎn)頁只包含了索引列,葉子頁包含行的全部數(shù)據(jù)堵第,這是B+Tree的數(shù)據(jù)結(jié)構(gòu)吧凉。在這個(gè)案例中,索引列包含的是整數(shù)值踏志。
圖1 聚簇索引的數(shù)據(jù)分布
InnoDB將通過主鍵聚集數(shù)據(jù)阀捅,圖1中的“被索引的列”就是主鍵列。如果沒有定義主鍵针余,InnoDB會選擇一個(gè)唯一的非空索引代替饲鄙。如果沒有這樣的索引,InnoDB會隱式定義一個(gè)主鍵來作為聚簇索引圆雁。InnoDB只聚集在同一個(gè)頁面中的記錄忍级,包含相鄰鍵值的頁面可能會相距甚遠(yuǎn)。
聚簇主鍵可能對性能有幫助伪朽,但也可能導(dǎo)致嚴(yán)重的性能問題轴咱。所以需要仔細(xì)地考慮聚簇索引,尤其是將表的存儲引擎從InnoDB改成其他引擎的時(shí)候(反過來也一樣)烈涮。
聚簇的數(shù)據(jù)有一些重要的優(yōu)點(diǎn):
可以把相關(guān)數(shù)據(jù)保存在一起朴肺。例如實(shí)現(xiàn)電子郵箱時(shí),可以根據(jù)用戶ID來聚集數(shù)據(jù)坚洽,這樣只需要從磁盤讀取少數(shù)的數(shù)據(jù)頁就能獲取某個(gè)用戶的全部郵件宇挫。如果沒有聚簇索引,則每封郵件都可能多一次磁盤IO酪术。
數(shù)據(jù)訪問更快。聚簇索引將索引和數(shù)據(jù)保存在同一個(gè)B+Tree中,因此從聚簇索引中獲取數(shù)據(jù)通常比在非聚簇索引中查找要快绘雁。
使用覆蓋索引掃描的查詢可以直接使用頁節(jié)點(diǎn)中的主鍵值橡疼。
如果設(shè)計(jì)表和查詢時(shí)能充分利用上面的優(yōu)點(diǎn),就能極大地提升性能庐舟。但是欣除,聚簇索引也有一些缺點(diǎn):
聚簇?cái)?shù)據(jù)最大限度地提高了IO密集型應(yīng)用的性能,但如果數(shù)據(jù)全部放在內(nèi)存中挪略,則訪問的順序就沒那么重要了历帚,聚簇索引也就沒什么優(yōu)勢了。
插入速度嚴(yán)重依賴于插入順序杠娱。按照主要的順序插入是加載數(shù)據(jù)到InnoDB表中速度最快的方式挽牢。但如果不是按照主鍵順序加載數(shù)據(jù),那么在加載完成后最好使用optimize table命令重新組織一下表摊求。
更新聚簇索引列的代價(jià)很高禽拔,因?yàn)闀?qiáng)制InnoDB將每個(gè)被更新的行移動(dòng)到新的位置。
基于聚簇索引的表插入新行室叉,或者主鍵被更新導(dǎo)致需要移動(dòng)行的時(shí)候睹栖,可能面臨”頁分裂(page split)“的問題。當(dāng)行的主鍵值要求必須將這一行插入到某個(gè)已滿的頁中時(shí)茧痕,存儲引擎會將該頁分裂成兩個(gè)頁面來容納該行野来,這就是一次分裂操作。頁分裂會導(dǎo)致表占用更多的磁盤空間踪旷。
聚簇索引可能導(dǎo)致全表掃描變慢曼氛,尤其是行比較稀疏,或者由于頁分裂導(dǎo)致數(shù)據(jù)存儲不連續(xù)的時(shí)候埃脏。
二級索引(非聚簇索引)可能比想象的要更大搪锣,因?yàn)樵诙o索引的葉子節(jié)點(diǎn)包含了引用行的主鍵列。
二級索引訪問需要兩次索引查找彩掐,而不是一次构舟。
最后一點(diǎn)可能讓人有些疑惑,為什么二級索引需要兩次索引查找堵幽?答案在于二級索引中保存的”行指針“的實(shí)質(zhì)狗超。要記住,二級索引葉子節(jié)點(diǎn)保存的不是指向行的物理位置的指針朴下,而是行的主鍵值努咐。
這意味著通過二級索引查找行,存儲引擎需要找到二級索引的葉子節(jié)點(diǎn)獲得對應(yīng)的主鍵值殴胧,然后根據(jù)這個(gè)值去聚簇索引中查找到對應(yīng)的行渗稍。這里做了重復(fù)的工作:兩次B-Tree查找而不是一次佩迟。對于 InnoDB,自適應(yīng)哈希索引能夠減少這樣的重復(fù)工作竿屹。
InnoDB和MyISAM的數(shù)據(jù)分布對比
聚簇索引和非聚簇索引的數(shù)據(jù)分布有區(qū)別报强,以及對應(yīng)的主要索引和二級索引的數(shù)據(jù)分布也有區(qū)別,通常會讓人感到困擾和意外拱燃。來看看InnoDB和MyISAM是如何存儲下面這個(gè)表的:
create tablelayout_test(? ? col1intnotnull,? ? col2intnotnull,? ? primary key(col1),key(col2));
假設(shè)該表的主鍵取值為1~10000秉溉,按照隨機(jī)順序播放并使用optimize table命令做了優(yōu)化。換句話說碗誉,數(shù)據(jù)在磁盤上的存儲方式已經(jīng)最優(yōu)召嘶,但行的順序是隨機(jī)的。列col2的值是從1~100之間隨機(jī)賦值哮缺,所以有很多重復(fù)的值弄跌。
MyISAM的數(shù)據(jù)布局
MyISAM的B+Tree的葉子節(jié)點(diǎn)上的data,并不是數(shù)據(jù)本身蝴蜓,而是數(shù)據(jù)存放的地址碟绑。MyISAM按照數(shù)據(jù)插入的順序存儲在磁盤上,如下圖2所示茎匠,左邊為行號(row number)局荚,從0開始编检。因?yàn)樵M的大小固定联四,所以MyISAM很容易的從表的開始位置找到某一字節(jié)的位置境蜕。
圖2 MyISAM表layout_test的數(shù)據(jù)分布
MyISAM建立的primary key的索引結(jié)構(gòu)大致如圖3和圖4所示。MyISAM不支持聚簇索引汽馋,索引中每一個(gè)葉子節(jié)點(diǎn)僅僅包含行號(row number)侮东,且葉子節(jié)點(diǎn)按照col1的順序存儲。MyISAM是按列值與行號來組織索引的豹芯。
圖3 MyISAM表layout_test的主鍵分布
在圖4中悄雅,表一共有三列,假設(shè)以Col1為主鍵铁蹈,可以看出宽闲,MyISAM的葉子節(jié)點(diǎn)中保存的實(shí)際上是指向存放數(shù)據(jù)的物理塊的指針。從MYISAM存儲的物理文件看出握牧,MyISAM引擎的索引文件(.MYI)和數(shù)據(jù)文件(.MYD)是相互獨(dú)立的容诬,索引文件僅僅保存數(shù)據(jù)記錄的地址。
圖4 MyISAM主鍵索引的分布
下圖5顯示col2 的索引結(jié)構(gòu)沿腰,與圖3的primary key對比览徒,索引中每一個(gè)葉子節(jié)點(diǎn)僅僅包含行號(row number),且葉子節(jié)點(diǎn)按照col2的順序存儲颂龙。在圖6中习蓬,在Col2建立一個(gè)輔助索引纽什,與圖4對比,MyISAM的葉子節(jié)點(diǎn)也是保存指向存放數(shù)據(jù)的物理塊的指針友雳。
所以稿湿,結(jié)論是MyISAM的primary key和輔助索引沒有任何區(qū)別。只是Primary key要求key唯一非空押赊,而輔助索引的key可以重復(fù)。
圖5 MyISAM表layout_test的col2列索引的分布
圖6 MyISAM輔助索引的分布
因此包斑,MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引流礁,如果指定的Key存在,則取出其data域的值罗丰,然后以data域的值為地址神帅,讀取相應(yīng)數(shù)據(jù)記錄。
InnoDB的數(shù)據(jù)布局
MyISAM索引文件和數(shù)據(jù)文件是分離的萌抵,索引文件僅保存數(shù)據(jù)記錄的地址找御。而在InnoDB中,表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu)绍填,這棵樹的葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄霎桅。這個(gè)索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引讨永。
圖7和與圖3 MyISAM對比看出滔驶,InnoDB索引的每一個(gè)葉子節(jié)點(diǎn)都包含了主鍵值、事務(wù)ID卿闹、用于事務(wù)和MVCC的回流指針以及所有的剩余列(在這個(gè)例子中是col2)揭糕。如果主鍵是一個(gè)列前綴索引,InnoDB也會包含完整的主鍵列和剩下的其他列锻霎。這種索引叫做聚簇索引著角。
圖8可以看到葉節(jié)點(diǎn)包含了完整的數(shù)據(jù)記錄。
因?yàn)镮nnoDB的數(shù)據(jù)文件本身要按主鍵聚集旋恼,所以InnoDB要求表必須有主鍵(MyISAM可以沒有)吏口,如果沒有顯式指定,則MySQL系統(tǒng)會自動(dòng)選擇一個(gè)可以唯一標(biāo)識數(shù)據(jù)記錄的列作為主鍵蚌铜,如果不存在這種列锨侯,則MySQL自動(dòng)為InnoDB表生成一個(gè)隱含字段作為主鍵,這個(gè)字段長度為6個(gè)字節(jié)冬殃,類型為長整形囚痴。
圖7 InnoDB表layout_test的主鍵分布
圖8 InnoDB主鍵索引的分布
還有一點(diǎn)和MyISAM的不同是,InnoDB的二級索引和聚簇索引很不相同审葬。InnoDB二級索引的葉子節(jié)點(diǎn)中存儲的不是”行指針“深滚,而是主鍵值奕谭,并以此作為指向行的“指針”。這樣的策略減少了當(dāng)出現(xiàn)行移動(dòng)或者數(shù)據(jù)頁分裂時(shí)二級索引的維護(hù)工作痴荐。使用主鍵值當(dāng)作指針會讓二級索引占用更多的空間血柳,換來的好處是,InnoDB在移動(dòng)行時(shí)無須更新二級索引中的這個(gè)“指針”生兆。
下圖9展示了示例表的二級索引col2索引难捌。每一個(gè)葉子節(jié)點(diǎn)都包含了索引列(這里是col2),緊接著是主鍵值(col1)鸦难。圖10展示了InnoDB的所有輔助索引都引用主鍵作為data域根吁。
圖9 InnoDB表layout_test的col2列索引的分布
圖10 InnoDB輔助索引的分布
InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一種非澈媳危快速的主鍵查找性能击敌。不過,它的輔助索引(Secondary Index拴事, 也就是非主鍵索引)也會包含主鍵列沃斤,所以,如果主鍵定義的比較大刃宵,其他索引也將很大衡瓶。如果想在表上定義 、很多索引组去,則爭取盡量把主鍵定義得小一些鞍陨。InnoDB 不會壓縮索引。
InnoDB與MyIASM索引和數(shù)據(jù)布局對比
圖7描述InnoDB和MyISAM如何存放表的抽象圖从隆。對比InnoDB和MyISAM的主鍵索引與二級索引诚撵。
InnoDB的的二級索引的葉子節(jié)點(diǎn)存放的是KEY字段加主鍵值。因此键闺,通過二級索引查詢首先查到是主鍵值寿烟,然后InnoDB再根據(jù)查到的主鍵值通過主鍵索引找到相應(yīng)的數(shù)據(jù)塊。而MyISAM的二級索引葉子節(jié)點(diǎn)存放的還是列值與行號的組合辛燥,葉子節(jié)點(diǎn)中保存的是數(shù)據(jù)的物理地址筛武。所以可以看出MYISAM的主鍵索引和二級索引沒有任何區(qū)別,主鍵索引僅僅只是一個(gè)叫做PRIMARY的唯一挎塌、非空的索引徘六,且MYISAM引擎中可以不設(shè)主鍵。
圖7 聚簇和非聚簇表對比圖
為了更形象說明這兩種索引的區(qū)別榴都,我們假想一個(gè)表如下圖8存儲了4行數(shù)據(jù)待锈。其中id作為主索引,name作為輔助索引嘴高。圖示清晰的顯示了聚簇索引和非聚簇索引的差異竿音。
對于聚簇索引存儲來說和屎,行數(shù)據(jù)和主鍵B+樹存儲在一起,輔助鍵B+樹只存儲輔助鍵和主鍵春瞬,主鍵和非主鍵B+樹幾乎是兩種類型的樹柴信。對于非聚簇索引存儲來說,主鍵B+樹在葉子節(jié)點(diǎn)存儲指向真正數(shù)據(jù)行的指針宽气,而非主鍵随常。
InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中抹竹,而行數(shù)據(jù)就儲存在葉子節(jié)點(diǎn)上线罕,若使用"where id = 14"這樣的條件查找主鍵,則按照B+樹的檢索算法即可查找到對應(yīng)的葉節(jié)點(diǎn)窃判,之后獲得行數(shù)據(jù)。若對Name列進(jìn)行條件搜索喇闸,則需要兩個(gè)步驟:第一步在輔助索引B+樹中檢索Name袄琳,到達(dá)其葉子節(jié)點(diǎn)獲取對應(yīng)的主鍵。第二步使用主鍵在主索引B+樹種再執(zhí)行一次B+樹檢索操作燃乍,最終到達(dá)葉子節(jié)點(diǎn)即可獲取整行數(shù)據(jù)唆樊。
MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什么不同刻蟹,節(jié)點(diǎn)的結(jié)構(gòu)完全一致只是存儲的內(nèi)容不同而已逗旁,主鍵索引B+樹的節(jié)點(diǎn)存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵舆瘪。表數(shù)據(jù)存儲在獨(dú)立的地方片效,這兩顆B+樹的葉子節(jié)點(diǎn)都使用一個(gè)地址指向真正的表數(shù)據(jù),對于表數(shù)據(jù)來說英古,這兩個(gè)鍵沒有任何差別淀衣。由于索引樹是獨(dú)立的,通過輔助鍵檢索無需訪問主鍵的索引樹召调。
圖8 聚簇和非聚簇表形象對比圖
我們重點(diǎn)關(guān)注聚簇索引膨桥,看上去聚簇索引的效率明顯要低于非聚簇索引,因?yàn)槊看问褂幂o助索引檢索都要經(jīng)過兩次B+樹查找唠叛,這不是多此一舉嗎只嚣?聚簇索引的優(yōu)勢在哪?
1 由于行數(shù)據(jù)和葉子節(jié)點(diǎn)存儲在一起艺沼,這樣主鍵和行數(shù)據(jù)是一起被載入內(nèi)存的册舞,找到葉子節(jié)點(diǎn)就可以立刻將行數(shù)據(jù)返回了,如果按照主鍵Id來組織數(shù)據(jù)澳厢,獲得數(shù)據(jù)更快环础。
2 輔助索引使用主鍵作為"指針" 而不是使用地址值作為指針的好處是囚似,減少了當(dāng)出現(xiàn)行移動(dòng)或者數(shù)據(jù)頁分裂時(shí)輔助索引的維護(hù)工作,使用主鍵值當(dāng)作指針會讓輔助索引占用更多的空間线得,換來的好處是InnoDB在移動(dòng)行時(shí)無須更新輔助索引中的這個(gè)"指針"饶唤。也就是說行的位置(實(shí)現(xiàn)中通過16K的Page來定位,后面會涉及)會隨著數(shù)據(jù)庫里數(shù)據(jù)的修改而發(fā)生變化(前面的B+樹節(jié)點(diǎn)分裂以及Page的分裂)贯钩,使用聚簇索引就可以保證不管這個(gè)主鍵B+樹的節(jié)點(diǎn)如何變化募狂,輔助索引樹都不受影響。
在InnoDB表中按主鍵順序插入行
如果正在使用InnoDB表并且沒有什么數(shù)據(jù)需要聚集角雷,那么可以定義一個(gè)代理鍵作為主鍵祸穷,這種主鍵的數(shù)據(jù)應(yīng)該和應(yīng)用無關(guān),最簡單的方法是使用auto_increment自增列勺三。這樣可以保證數(shù)據(jù)行是按照順序?qū)懭肜坠觯瑢τ诟鶕?jù)主鍵做關(guān)聯(lián)操作的性能也會更好。
最好避免隨機(jī)的聚簇索引吗坚,特別對于I/O密集型的應(yīng)用祈远。例如,從性能的角度考慮商源,使用UUID作為聚簇索引會很糟糕:它使得聚簇索引的插入變得完全隨機(jī)车份,這是最壞的情況,使得數(shù)據(jù)沒有任何聚集特性牡彻。
為了演示這一點(diǎn)扫沼,我們做如下兩個(gè)基準(zhǔn)測試。第一個(gè)使用整數(shù)ID插入shopinfo表庄吼,整數(shù)ID自增且為主鍵:
CREATE TABLE`shopinfo`(`id`int(11) NOT NULL AUTO_INCREMENT COMMENT'記錄ID',`shop_id`int(11) NOT NULL COMMENT'商店ID',`goods_id`int(11) NOT NULL COMMENT'物品ID',`pay_type`tinyint(1) NOT NULL COMMENT'支付方式',`price`decimal(10,2) NOT NULL COMMENT'物品價(jià)格',`comment`varchar(4000) DEFAULT NULL,? PRIMARY KEY (`id`),? UNIQUE KEY`shop_id`(`shop_id`,`goods_id`),? KEY`price`(`price`),? KEY`pay_type`(`pay_type`),? KEY`idx_comment`(`comment`(255))) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商店物品表';
第二個(gè)例子是shopinfo_uuid表缎除,除了主鍵改為UUID,其余和前面的shopinfo表完全相同霸褒。
CREATE TABLE`shopinfo_uuid`(`uuid`varchar(36) NOT NULL,`shop_id`int(11) NOT NULL COMMENT'商店ID',`goods_id`int(11) NOT NULL COMMENT'物品ID',`pay_type`tinyint(1) NOT NULL COMMENT'支付方式',`price`decimal(10,2) NOT NULL COMMENT'物品價(jià)格',`comment`varchar(4000) DEFAULT NULL,? PRIMARY KEY (`uuid`),? UNIQUE KEY`shop_id`(`shop_id`,`goods_id`),? KEY`price`(`price`),? KEY`pay_type`(`pay_type`),? KEY`idx_comment`(`comment`(255))) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商店物品表';
我們先向這兩個(gè)表各插入1萬條記錄伴找。然后再向這兩個(gè)表繼續(xù)插入9萬條記錄,觀察這兩個(gè)表的插入耗時(shí)和表索引大小废菱,下表對測試結(jié)果進(jìn)行比較技矮。其中,查看指定庫的指定表shopinfo的索引大小SQL語句:
SELECT CONCAT(ROUND(SUM(index_length)/(1024*1024), 2), ' MB') AS 'Total Index Size' FROM TABLES WHERE table_schema = 'study' and table_name = 'shopinfo';
表名行數(shù)時(shí)間索引大惺庵帷(MB)
shopinfo100000.755s4.08
shopinfo_uuid100001.699s8.16
shopinfo900008.014s29.47
shopinfo_uuid9000046.111s60.58
通過測試衰倦,插入同樣的行數(shù)和內(nèi)容(除主鍵內(nèi)容),向UUID主鍵插入行不僅花費(fèi)的時(shí)間更長旁理,而且索引占用的空間也更大樊零。這一方面是由于主鍵字段更長,另一方面毫無疑問是由于頁分裂和碎片導(dǎo)致的。
如圖9所示驻襟,由于主鍵的值是順序的夺艰,InnoDB把每一條記錄都存儲在上一條記錄的后面。當(dāng)達(dá)到頁的最大填充因子時(shí)(InnoDB默認(rèn)的最大填充因子是頁大小的15/16沉衣,留出的部分空間用于以后修改)郁副,下一條記錄就會寫入新的頁中。一旦數(shù)據(jù)按照這樣順序的方式加載豌习,主鍵頁就會近似于被順序的記錄填滿存谎,這也是所期望的結(jié)果。
圖9 向聚簇索引插入順序的索引值
而當(dāng)采用UUID的聚簇索引的表往插入數(shù)據(jù)肥隆,如圖10所示既荚,因?yàn)樾滦械闹麈I值不一定比之前的插入值大,所以InnoDB無法簡單的總是把新行插入到索引的最后栋艳,而是需要為新的行尋找合適的位置----通常是已有數(shù)據(jù)的中間位置----并且分配空間恰聘。這會增加很多額外的工作,并導(dǎo)致數(shù)據(jù)分布不夠優(yōu)化吸占。
圖10 向聚簇索引插入無序的值
下面總結(jié)使用UUID作為主鍵的一些缺點(diǎn):
寫入目標(biāo)頁可能已經(jīng)刷到磁盤上并從緩存中移除憨琳,或者是還沒有被加載到緩存中,InnoDB在插入之前不得不先找到并從磁盤讀取目標(biāo)頁到內(nèi)存中旬昭,這將導(dǎo)致大量的隨機(jī)I/O;
因?yàn)閷懭胧莵y序的菌湃,InnoDB不得不頻繁的做頁分裂操作问拘,以便為新的行分配空間。頁分裂會導(dǎo)致移動(dòng)大量數(shù)據(jù)惧所,一次插入最少需要修改三個(gè)頁而不是一個(gè)骤坐,包含兩個(gè)葉子節(jié)點(diǎn)和一個(gè)父節(jié)點(diǎn)。
由于頻繁的頁分裂下愈,頁會變得稀疏并被不規(guī)則的填充纽绍,所以最終數(shù)據(jù)會有碎片。
把這些隨機(jī)值載入到聚簇索引以后势似,需要做一次optimize table來重建表并優(yōu)化頁的填充拌夏。
注意,順序主鍵也有缺點(diǎn):對于高并發(fā)工作負(fù)載履因,在InnoDB中按主鍵順序插入可能會造成明顯的爭用障簿。主鍵的上界會成為“熱點(diǎn)”。因?yàn)樗械牟迦攵及l(fā)生在這里栅迄,所以并發(fā)插入可能導(dǎo)致間隙鎖競爭站故。另一個(gè)熱點(diǎn)可能是auto_increment鎖機(jī)制;如果遇到這個(gè)問題毅舆,則可能需要考慮重新設(shè)計(jì)表或者應(yīng)用西篓,比如應(yīng)用層面生成單調(diào)遞增的主鍵ID愈腾,插表不使用auto_increment機(jī)制,或者更改innodb_autonc_lock_mode配置岂津。
作者:大頭8086
鏈接:http://www.reibang.com/p/54c6d5db4fe6
來源:簡書
著作權(quán)歸作者所有虱黄。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處寸爆。