MySQL 分库分表与分区的区别和思考
一.分分合合
說(shuō)過(guò)很多次,不要拘泥于某一個(gè)技術(shù)的一點(diǎn),技術(shù)是相通的。重要的是編程思想,思想是最重要的。當(dāng)數(shù)據(jù)量大的時(shí)候,需要具有分的思想去細(xì)化粒度。當(dāng)數(shù)據(jù)量太碎片的時(shí)候,需要具有合的思想來(lái)粗化粒度。
1.1 分
很多技術(shù)都運(yùn)用了分的編程思想,這里來(lái)舉幾個(gè)例子,這些都是分的思想
集中式服務(wù)發(fā)展到分布式服務(wù)
從Collections.synchronizedMap(x)到1.7ConcurrentHashMap再到1.8ConcurrentHashMap,細(xì)化鎖的粒度的同時(shí)依舊保證線程安全
從AtomicInteger到LongAdder,ConcurrentHashMap的size()方法。用分散思想,減少cas次數(shù),增強(qiáng)多線程對(duì)一個(gè)數(shù)的累加
JVM的G1 GC算法,將堆分成很多Region來(lái)進(jìn)行內(nèi)存管理
Hbase的RegionServer中,將數(shù)據(jù)分成多個(gè)Region進(jìn)行管理
平時(shí)開(kāi)發(fā)是不是線程池都資源隔離
2.2 合
很多技術(shù)也運(yùn)用到了合的編程思想,這里舉幾個(gè)例子,這些都是合的思想
TLAB(Thread Local Allocation Buffers),線程本地分配緩存。避免多線程沖突,提高對(duì)象分配效率
逃逸分析,將變量的實(shí)例化內(nèi)存直接在棧里分配,無(wú)需進(jìn)入堆,線程結(jié)束棧空間被回收。減少臨時(shí)對(duì)象在堆內(nèi)分配數(shù)量
CMS GC算法下,雖然使用標(biāo)記清除,但是也有配置支持整理內(nèi)存碎片。如:-XX:UseCMS-CompactAtFullCollection(FullGC后是否整理,Stop The World會(huì)變長(zhǎng))和-XX:CMSFullGCs-BeforeCompaction(幾次FullGC之后進(jìn)行壓縮整理)
鎖粗化,當(dāng)JIT發(fā)現(xiàn)一系列連續(xù)的操作都是對(duì)同一對(duì)象反復(fù)加鎖和釋放鎖,會(huì)加大鎖同步的范圍
kafka的網(wǎng)絡(luò)數(shù)據(jù)傳輸有一些數(shù)據(jù)配置,減少網(wǎng)絡(luò)開(kāi)銷(xiāo)。如:batch.size和linger.ms等等
平時(shí)開(kāi)發(fā)是不是都個(gè)叫批量獲取接口
二.分區(qū)
本文一切基于MySql InnoDB
說(shuō)了這么多,接下來(lái)說(shuō)主體,先說(shuō)分區(qū),因?yàn)橹安┲鲗?xiě)過(guò)一篇MySql分區(qū)的博客所以這里不會(huì)多費(fèi)筆墨來(lái)寫(xiě),具體見(jiàn):
cnblogs.com/GrimMjx/p/10526821.html
2.1 實(shí)現(xiàn)方式
具體如何實(shí)現(xiàn)上面鏈接里有寫(xiě),這里只需記住如果表中存在主鍵或唯一索引時(shí),分區(qū)列必須是唯一索引的一個(gè)組成部分。
這個(gè)是數(shù)據(jù)庫(kù)分的,應(yīng)用透明,代碼無(wú)需修改任何東西。
2.2 內(nèi)部文件
先去data目錄,如果不知道目錄位置的可以執(zhí)行:
接下來(lái)看下內(nèi)部文件:
?
?
從上圖我們可以看出,有2中類(lèi)型的文件,.frm文件和.ibd文件
frm文件:表結(jié)構(gòu)文件
ibd文件:InnoDB中,索引和數(shù)據(jù)都在同個(gè)文件.ibdata(你的執(zhí)行結(jié)果可能是.MYD索引文件和.MYI數(shù)據(jù)文件,沒(méi)關(guān)系,這是MyIsAm存儲(chǔ)引擎,對(duì)應(yīng)著InnoDB的.ibd文件)。因?yàn)镺rder這張表分為5個(gè)區(qū),所以有5個(gè)這樣的文件
par文件:你執(zhí)行的結(jié)果可能有.par文件也可能沒(méi)有。注意:從MySql 5.7.6開(kāi)始,不再創(chuàng)建.par分區(qū)定義文件。分區(qū)定義存儲(chǔ)在內(nèi)部數(shù)據(jù)字典中。
2.3 數(shù)據(jù)處理
分區(qū)表后,提高了MySql性能。如果一張表的話,那就只有一個(gè).ibd文件,一顆大的B+樹(shù)。如果分表后,將按分區(qū)規(guī)則,分成不同的區(qū),也就是一個(gè)大的B+樹(shù),分成多個(gè)小的樹(shù)。
(PS:如果想研究一顆聚集索引B+樹(shù)可以放多少行數(shù)據(jù),請(qǐng)看:cnblogs.com/GrimMjx/p/10540263.html)
讀的效率肯定提升了,如果走分區(qū)鍵索引的話,先走對(duì)應(yīng)分區(qū)的輔助索引B+樹(shù),再走對(duì)應(yīng)分區(qū)的聚集索引B+樹(shù)。
如果沒(méi)有走分區(qū)鍵,將會(huì)在所有分區(qū)都會(huì)執(zhí)行一次。會(huì)造成多次邏輯IO!平時(shí)開(kāi)發(fā)如果想查看sql語(yǔ)句的分區(qū)查詢可以使用explain partitons select xxxxx語(yǔ)句。可以看到一句select語(yǔ)句走了幾個(gè)分區(qū)。
mysql> explain partitions select * from TxnList where startTime>'2016-08-25 00:00:00' and startTime<'2016-08-25 23:59:00'; +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ | 1 | SIMPLE | ClientActionTrack | p20160825 | ALL | NULL | NULL | NULL | NULL | 33868 | Using where | +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ row in set (0.00 sec)三.分庫(kù)分表
當(dāng)一張表隨著時(shí)間和業(yè)務(wù)的發(fā)展,庫(kù)里表的數(shù)據(jù)量會(huì)越來(lái)越大。數(shù)據(jù)操作也隨之會(huì)越來(lái)越大。一臺(tái)物理機(jī)的資源有限,最終能承載的數(shù)據(jù)量、數(shù)據(jù)的處理能力都會(huì)受到限制。這時(shí)候就會(huì)使用分庫(kù)分表來(lái)承接超大規(guī)模的表,單機(jī)放不下的那種。
區(qū)別于分區(qū)的是,分區(qū)一般都是放在單機(jī)里的,用的比較多的是時(shí)間范圍分區(qū),方便歸檔。只不過(guò)分庫(kù)分表需要代碼實(shí)現(xiàn),分區(qū)則是mysql內(nèi)部實(shí)現(xiàn)。分庫(kù)分表和分區(qū)并不沖突,可以結(jié)合使用。
?
3.1 實(shí)現(xiàn)
3.1.1 分庫(kù)分表標(biāo)準(zhǔn)
-
存儲(chǔ)占用100G+
-
數(shù)據(jù)增量每天200w+
-
單表?xiàng)l數(shù)1億條+
3.1.2 分庫(kù)分表字段
分庫(kù)分表字段取值非常重要
1.在大多數(shù)場(chǎng)景該字段是查詢字段
2.數(shù)值型
一般使用userId,可以滿足上述條件
3.2 分布式數(shù)據(jù)庫(kù)中間件
分布式數(shù)據(jù)庫(kù)中間件分為兩種,proxy和客戶端式架構(gòu)。proxy模式有MyCat、DBProxy等,客戶端式架構(gòu)有TDDL、Sharding-JDBC等。那么proxy和客戶端式架構(gòu)有何區(qū)別呢?各自有什么優(yōu)缺點(diǎn)呢?其實(shí)看一張圖便可知曉。
proxy模式的話我們的select和update語(yǔ)句都是發(fā)送給代理,由這個(gè)代理來(lái)操作具體的底層數(shù)據(jù)庫(kù)。所以必須要求代理本身需要保證高可用,否則數(shù)據(jù)庫(kù)沒(méi)有宕機(jī),proxy掛了,那就走遠(yuǎn)了。
客戶端模式通常在連接池上做了一層封裝,內(nèi)部與不同的庫(kù)連接,sql交給smart-client進(jìn)行處理。通常僅支持一種語(yǔ)言,如果其他語(yǔ)言要使用,需要開(kāi)發(fā)多語(yǔ)言客戶端。
各自的優(yōu)缺點(diǎn)如下:
3.3 內(nèi)部文件
找了一個(gè)分庫(kù)分表+分區(qū)的例子,基本上和分區(qū)表的差不多,只是多了多了很多表的.ibd文件,上面有文件的解釋:
[miaojiaxing@Grim testmydata]# ls | grep 'base_info'base_info_00.frmbase_info_00#P#p_2018.ibdbase_info_00#P#p_2019.ibdbase_info_00#P#p_2020.ibdbase_info_00#P#p_2021.ibdbase_info_00#P#p_init.ibdbase_info_00#P#p_max.ibdbase_info_01.frmbase_info_01#P#p_2018.ibdbase_info_01#P#p_2019.ibdbase_info_01#P#p_2020.ibdbase_info_01#P#p_2021.ibdbase_info_01#P#p_init.ibdbase_info_01#P#p_max.ibdbase_info.frmbase_info.ibd3.4 問(wèn)題
3.4.1 事務(wù)問(wèn)題
既然分庫(kù)分表了,那么肯定涉及到分布式事務(wù),如何保證插入到不同庫(kù)的多條記錄能夠要么同時(shí)成功,要么同時(shí)失敗。有些同學(xué)可能想到XA,XA性能差而且不需要使用mysql5.7。柔性事務(wù)是目前主流的方案,TCC模式就屬于柔性事務(wù)。
對(duì)于分布式事務(wù)問(wèn)題每家公司有自己的實(shí)現(xiàn),華為用saga,阿里用TXC,螞蟻用DTX,支持FMT模式和TCC模式。
3.4.2 join問(wèn)題
tddl、MyCAT等都支持跨分片join。但是盡力避免跨庫(kù)join,比如通過(guò)字段冗余的方式等。
如果出現(xiàn)了這種情況且中間件支持分片join,那么可以這樣使用。如果不支持可以手工查詢。
四.總結(jié)
分表和在用途上不一樣,分表是為了承接超大規(guī)模的表,單機(jī)放不下那種。
分區(qū)的話則一般都是放在單機(jī)里的,用的比較多的是時(shí)間范圍分區(qū),方便歸檔。
性能穩(wěn)定上的話都是一個(gè)個(gè)子表,差不多,區(qū)別應(yīng)該是分區(qū)表是mysql內(nèi)部實(shí)現(xiàn)的,會(huì)比分表方案少一點(diǎn)數(shù)據(jù)交互只要你堅(jiān)持,一步一步來(lái),總歸會(huì)成功的。
切忌,學(xué)技術(shù)急不來(lái),快就是穩(wěn),穩(wěn)就是快。技術(shù)有限,接收指正。如果您覺(jué)得寫(xiě)的可以,請(qǐng)點(diǎn)個(gè)推薦。
總結(jié)
以上是生活随笔為你收集整理的MySQL 分库分表与分区的区别和思考的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spring Boot 五种热部署方式,
- 下一篇: 卧底各大程序员圈,才知道什么才是牛逼的程