1史煎、給出一個(gè)技術(shù)可實(shí)現(xiàn)的數(shù)據(jù)庫分表的標(biāo)準(zhǔn)
關(guān)系型數(shù)據(jù)庫本身比較容易成為系統(tǒng)瓶頸衩藤,單機(jī)存儲(chǔ)容量吧慢、連接數(shù)、處理能力都有限赏表。當(dāng)單表的數(shù)據(jù)量達(dá)到1000W或100G以后检诗,由于查詢維度較多,即使添加從庫瓢剿、優(yōu)化索引逢慌,做很多操作時(shí)性能仍下降嚴(yán)重。此時(shí)就要考慮對(duì)其進(jìn)行切分了间狂,切分的目的就在于減少數(shù)據(jù)庫的負(fù)擔(dān)攻泼,縮短查詢時(shí)間。
數(shù)據(jù)庫分布式核心內(nèi)容無非就是數(shù)據(jù)切分(Sharding),以及切分后對(duì)數(shù)據(jù)的定位忙菠、整合何鸡。數(shù)據(jù)切分就是將數(shù)據(jù)分散存儲(chǔ)到多個(gè)數(shù)據(jù)庫中,使得單一數(shù)據(jù)庫中的數(shù)據(jù)量變小牛欢,通過擴(kuò)充主機(jī)的數(shù)量緩解單一數(shù)據(jù)庫的性能問題骡男,從而達(dá)到提升數(shù)據(jù)庫操作性能的目的。
數(shù)據(jù)切分根據(jù)其切分類型傍睹,可以分為兩種方式:垂直(縱向)切分和水平(橫向)切分隔盛。
1)垂直切分常見有垂直分庫和垂直分表兩種。
垂直分庫就是根據(jù)業(yè)務(wù)耦合性焰望,將關(guān)聯(lián)度低的不同表存儲(chǔ)在不同的數(shù)據(jù)庫骚亿。做法與大系統(tǒng)拆分為多個(gè)小系統(tǒng)類似,按業(yè)務(wù)分類進(jìn)行獨(dú)立劃分熊赖。與"微服務(wù)治理"的做法相似,每個(gè)微服務(wù)使用單獨(dú)的一個(gè)數(shù)據(jù)庫虑椎。
垂直分表是基于數(shù)據(jù)庫中的"列"進(jìn)行震鹉,某個(gè)表字段較多,可以新建一張擴(kuò)展表捆姜,將不經(jīng)常用或字段長(zhǎng)度較大的字段拆分出去到擴(kuò)展表中传趾。
2)水平切分
當(dāng)一個(gè)應(yīng)用難以再細(xì)粒度的垂直切分,或切分后數(shù)據(jù)量行數(shù)巨大泥技,存在單庫讀寫浆兰、存儲(chǔ)性能瓶頸,這時(shí)候就需要進(jìn)行水平切分了珊豹。
水平切分分為庫內(nèi)分表和分庫分表簸呈,是根據(jù)表內(nèi)數(shù)據(jù)內(nèi)在的邏輯關(guān)系,將同一個(gè)表按不同的條件分散到多個(gè)數(shù)據(jù)庫或多個(gè)表中店茶,每個(gè)表中只包含一部分?jǐn)?shù)據(jù)蜕便,從而使得單個(gè)表的數(shù)據(jù)量變小,達(dá)到分布式的效果贩幻。
庫內(nèi)分表只解決了單一表數(shù)據(jù)量過大的問題轿腺,但沒有將表分布到不同機(jī)器的庫上,因此對(duì)于減輕MySQL數(shù)據(jù)庫的壓力來說丛楚,幫助不是很大族壳,大家還是競(jìng)爭(zhēng)同一個(gè)物理機(jī)的CPU、內(nèi)存趣些、網(wǎng)絡(luò)IO仿荆,最好通過分庫分表來解決。
幾種典型的數(shù)據(jù)分片規(guī)則為:
● 根據(jù)數(shù)值范圍
按照時(shí)間區(qū)間或ID區(qū)間來切分。例如:按日期將不同月甚至是日的數(shù)據(jù)分散到不同的庫中赖歌;將userId為1~9999的記錄分到第一個(gè)庫枉圃,10000~20000的分到第二個(gè)庫,以此類推庐冯。某種意義上孽亲,某些系統(tǒng)中使用的"冷熱數(shù)據(jù)分離",將一些使用較少的歷史數(shù)據(jù)遷移到其他庫中展父,業(yè)務(wù)功能上只提供熱點(diǎn)數(shù)據(jù)的查詢返劲,也是類似的實(shí)踐。
● 根據(jù)數(shù)值取模
一般采用hash取模mod的切分方式栖茉,例如:將 Customer 表根據(jù) cusno 字段切分到4個(gè)庫中篮绿,余數(shù)為0的放到第一個(gè)庫,余數(shù)為1的放到第二個(gè)庫吕漂,以此類推亲配。這樣同一個(gè)用戶的數(shù)據(jù)會(huì)分散到同一個(gè)庫中,如果查詢條件帶有cusno字段惶凝,則可明確定位到相應(yīng)庫去查詢吼虎。
分庫分表帶來的問題:
●?事務(wù)一致性問題
可使用分布式事務(wù)和最終一致性解決。
●?跨節(jié)點(diǎn)關(guān)聯(lián)查詢 join 問題
●?跨節(jié)點(diǎn)分頁苍鲜、排序思灰、函數(shù)問題
●?全局主鍵避重問題
在分庫分表環(huán)境中,由于表中數(shù)據(jù)同時(shí)存在不同數(shù)據(jù)庫中混滔,主鍵值平時(shí)使用的自增長(zhǎng)將無用武之地洒疚,某個(gè)分區(qū)數(shù)據(jù)庫自生成的ID無法保證全局唯一。因此需要單獨(dú)設(shè)計(jì)全局主鍵坯屿,以避免跨庫主鍵重復(fù)問題油湖。
●?數(shù)據(jù)遷移、擴(kuò)容問題
3)什么時(shí)候考慮切分
能不切分盡量不要切分
數(shù)據(jù)量過大愿伴,正常運(yùn)維影響業(yè)務(wù)訪問
隨著業(yè)務(wù)發(fā)展肺魁,需要對(duì)某些字段垂直拆分
數(shù)據(jù)量快速增長(zhǎng),考慮水平拆分
安全性和可用性
參考:http://www.west999.com/info/html/wangluobiancheng/Mysql/20190724/4651529.html
2隔节、Mysql自增的主鍵鹅经,改為隨機(jī)生成的唯一字符串,如何給出合理理由怎诫?
????自增的缺點(diǎn)
????1瘾晃,要維護(hù)自增鎖
????2,對(duì)水平拆分不友好
????3幻妓,業(yè)務(wù)不安全蹦误,比如輕易就能推斷出一段時(shí)間內(nèi)的數(shù)據(jù)量
3劫拢、聚簇索引與非聚簇索引?
索引的原理(https://blog.csdn.net/u013308490/article/details/83001060、https://www.cnblogs.com/bypp/p/7755307.html):
目前大部分?jǐn)?shù)據(jù)庫系統(tǒng)及文件系統(tǒng)都采用B-Tree(B樹)或其變種B+Tree(B+樹)作為索引結(jié)構(gòu)强胰。B+Tree是數(shù)據(jù)庫系統(tǒng)實(shí)現(xiàn)索引的首選數(shù)據(jù)結(jié)構(gòu)舱沧。在MySQL中,索引屬于存儲(chǔ)引擎級(jí)別的概念,不同存儲(chǔ)引擎對(duì)索引的實(shí)現(xiàn)方式是不同的,本文主要討論MyISAM和InnoDB兩個(gè)存儲(chǔ)引擎的索引實(shí)現(xiàn)方式。
MyISAM引擎使用B+Tree作為索引結(jié)構(gòu),葉節(jié)點(diǎn)的data域存放的是數(shù)據(jù)記錄的地址偶洋。InnoDB引擎使用B+Tree作為索引結(jié)構(gòu),葉節(jié)點(diǎn)的data域存放的是完整的數(shù)據(jù)記錄熟吏。
一、MyISAM 索引實(shí)現(xiàn)?
MyISAM 引擎使用 B+Tree 作為索引結(jié)構(gòu),葉節(jié)點(diǎn)的 data 域存放的是數(shù)據(jù)記錄的地址玄窝。
這里設(shè)表一共有三列,假設(shè)我們以 Col1 為主鍵,則圖 8 是一個(gè) MyISAM 表的主索引(Primary key)示意牵寺。可以看出 MyISAM 的索引文件僅僅保存數(shù)據(jù)記錄的地址恩脂。
輔助索引?
在 MyISAM 中,主索引和輔助索引(Secondary key)在結(jié)構(gòu)上沒有任何區(qū)別,只是主索引要求 key 是唯一的,而輔助索引的 key 可以重復(fù)帽氓。如果我們?cè)?Col2 上建立一個(gè)輔助索引。同樣也是一顆 B+Tree,data 域保存數(shù)據(jù)記錄的地址俩块。因此,MyISAM 中索引檢索的算法為首先按照 B+Tree 搜索算法搜索索引,如果指定的 Key 存在,則取出其data 域的值,然后以 data 域的值為地址,讀取相應(yīng)數(shù)據(jù)記錄黎休。
MyISAM 的索引方式也叫做“非聚集索引”,之所以這么稱呼是為了與 InnoDB的聚集索引區(qū)分。
二玉凯、InnoDB 索引實(shí)現(xiàn)?
雖然 InnoDB 也使用 B+Tree 作為索引結(jié)構(gòu),但具體實(shí)現(xiàn)方式卻與 MyISAM 截然不同奋渔。
1.第一個(gè)重大區(qū)別是 InnoDB 的數(shù)據(jù)文件本身就是索引文件。從上文知道,MyISAM 索引文件和數(shù)據(jù)文件是分離的,索引文件僅保存數(shù)據(jù)記錄的地址壮啊。
而在InnoDB 中,表數(shù)據(jù)文件本身就是按 B+Tree 組織的一個(gè)索引結(jié)構(gòu),這棵樹的葉點(diǎn)data 域保存了完整的數(shù)據(jù)記錄。這個(gè)索引的 key 是數(shù)據(jù)表的主鍵,因此?InnoDB 表數(shù)據(jù)文件本身就是主索引撑蒜。
上圖是 InnoDB 主索引(同時(shí)也是數(shù)據(jù)文件)的示意圖,可以看到葉節(jié)點(diǎn)包含了完整的數(shù)據(jù)記錄歹啼。這種索引叫做聚集索引。因?yàn)?InnoDB 的數(shù)據(jù)文件本身要按主鍵聚集座菠。
1.InnoDB 要求表必須有主鍵(MyISAM 可以沒有),如果沒有顯式指定,則 MySQL系統(tǒng)會(huì)自動(dòng)選擇一個(gè)可以唯一標(biāo)識(shí)數(shù)據(jù)記錄的列作為主鍵,如果不存在這種列,則MySQL 自動(dòng)為 InnoDB 表生成一個(gè)隱含字段作為主鍵,類型為長(zhǎng)整形狸眼。
同時(shí),請(qǐng)盡量在 InnoDB 上采用自增字段做表的主鍵。因?yàn)?InnoDB 數(shù)據(jù)文件本身是一棵B+Tree,非單調(diào)的主鍵會(huì)造成在插入新記錄時(shí)數(shù)據(jù)文件為了維持 B+Tree 的特性而頻繁的分裂調(diào)整,十分低效,而使用自增字段作為主鍵則是一個(gè)很好的選擇浴滴。如果表使用自增主鍵,那么每次插入新的記錄,記錄就會(huì)順序添加到當(dāng)前索引節(jié)點(diǎn)的后續(xù)位置,當(dāng)一頁寫滿,就會(huì)自動(dòng)開辟一個(gè)新的頁拓萌。
2.第二個(gè)與 MyISAM 索引的不同是 InnoDB 的輔助索引 data 域存儲(chǔ)相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB 的所有輔助索引都引用主鍵作為 data 域升略。
聚集索引這種實(shí)現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄微王。
?引申:為什么不建議使用過長(zhǎng)的字段作為主鍵?
?因?yàn)樗休o助索引都引用主索引,過長(zhǎng)的主索引會(huì)令輔助索引變得過大品嚣。
InnoDB有了聚簇索引炕倘,為什么還要有二級(jí)索引呢?
聚簇索引的葉子節(jié)點(diǎn)存儲(chǔ)了一行完整的數(shù)據(jù)翰撑,而二級(jí)索引只存儲(chǔ)了主鍵值罩旋,相比于聚簇索引,占用的空間要少。當(dāng)我們需要為表建立多個(gè)索引時(shí)涨醋,如果都是聚簇索引瓜饥,那將占用大量?jī)?nèi)存空間,所以InnoDB中主鍵所建立的是聚簇索引浴骂,而唯一索引乓土、普通索引、前綴索引等都是二級(jí)索引靠闭。
為什么一般情況下帐我,我們建表的時(shí)候都會(huì)使用一個(gè)自增的id來作為我們的主鍵?
InnoDB中表中的數(shù)據(jù)是直接存儲(chǔ)在主鍵聚簇索引的葉子節(jié)點(diǎn)中的愧膀,每插入一條記錄拦键,其實(shí)都是增加一個(gè)葉子節(jié)點(diǎn),如果主鍵是順序的檩淋,只需要把新增的一條記錄存儲(chǔ)在上一條記錄的后面芬为,當(dāng)頁達(dá)到最大填充因子的時(shí)候,下一跳記錄就會(huì)寫入新的頁中蟀悦,這種情況下媚朦,主鍵頁就會(huì)近似于被順序的記錄填滿。
若表的主鍵不是順序的id日戈,而是無規(guī)律數(shù)據(jù)询张,比如字符串,InnoDB無法加單的把一行記錄插入到索引的最后浙炼,而是需要找一個(gè)合適的位置(已有數(shù)據(jù)的中間位置)份氧,甚至產(chǎn)生大量的頁分裂并且移動(dòng)大量數(shù)據(jù),在尋找合適位置進(jìn)行插入時(shí)弯屈,目標(biāo)頁可能不在內(nèi)存中蜗帜,這就導(dǎo)致了大量的隨機(jī)IO操作,影響插入效率资厉。除此之外厅缺,大量的頁分裂會(huì)導(dǎo)致大量的內(nèi)存碎片。
聚簇索引與非聚簇索引?
InnoDB 使用的是聚簇索引, 將主鍵組織到一棵 B+樹中, 而行數(shù)據(jù)就儲(chǔ)存在葉子節(jié)點(diǎn)上, 若使用"where id = 14"這樣的條件查找主鍵, 則按照 B+樹的檢索算法即可查找到對(duì)應(yīng)的葉節(jié)點(diǎn), 之后獲得行數(shù)據(jù)宴偿。 若對(duì) Name 列進(jìn)行條件搜索, 則需要兩個(gè)步驟:
第一步在輔助索引 B+樹中檢索 Name, 到達(dá)其葉子節(jié)點(diǎn)獲取對(duì)應(yīng)的主鍵湘捎。
第二步使用主鍵在主索引 B+樹種再執(zhí)行一次 B+樹檢索操作, 最終到達(dá)葉子節(jié)點(diǎn)即可獲取整行數(shù)據(jù)。
MyISM 使用的是非聚簇索引, 非聚簇索引的兩棵 B+樹看上去沒什么不同, 節(jié)點(diǎn)的結(jié)構(gòu)完全一致只是存儲(chǔ)的內(nèi)容不同而已, 主鍵索引 B+樹的節(jié)點(diǎn)存儲(chǔ)了主鍵, 輔助鍵索引B+樹存儲(chǔ)了輔助鍵酪我。 表數(shù)據(jù)存儲(chǔ)在獨(dú)立的地方, 這兩顆 B+樹的葉子節(jié)點(diǎn)都使用一個(gè)地址指向真正的表數(shù)據(jù), 對(duì)于表數(shù)據(jù)來說, 這兩個(gè)鍵沒有任何差別消痛。 由于索引樹是獨(dú)立的, 通過輔助鍵檢索無需訪問主鍵的索引樹。
為了更形象說明這兩種索引的區(qū)別, 我們假想一個(gè)表如下圖存儲(chǔ)了 4 行數(shù)據(jù)都哭。 其中Id 作為主索引, Name 作為輔助索引秩伞。 圖示清晰的顯示了聚簇索引和非聚簇索引的差異:
聯(lián)合索引及最左原則
最左原則:
例如聯(lián)合索引有三個(gè)索引字段(A,B,C)
查詢條件:
(A逞带,,)---會(huì)使用索引
(A纱新,B展氓,)---會(huì)使用索引
(A,B脸爱,C)---會(huì)使用索引
(遇汞,B,C)---不會(huì)使用索引
(簿废,空入,C)---不會(huì)使用索引