MyBatis實(shí)現(xiàn)Mysql數(shù)據(jù)庫(kù)分庫(kù)分表操作和總結(jié)(推薦)
前言
作為一個(gè)數(shù)據(jù)庫(kù),作為數(shù)據(jù)庫(kù)中的一張表,隨著用戶的增多隨著時(shí)間的推移,總有一天,數(shù)據(jù)量會(huì)大到一個(gè)難以處理的地步。這時(shí)僅僅一張表的數(shù)據(jù)就已經(jīng)超過(guò)了千萬(wàn),無(wú)論是查詢還是修改,對(duì)于它的操作都會(huì)很耗時(shí),這時(shí)就需要進(jìn)行數(shù)據(jù)庫(kù)切分的操作了。
MyBatis實(shí)現(xiàn)分表最簡(jiǎn)單步驟
既然文章的標(biāo)題都這么寫了,不如直接上干貨來(lái)的比較實(shí)際,我們就先來(lái)看看如何實(shí)現(xiàn)最簡(jiǎn)單的分表。
1、我們模擬用戶表數(shù)據(jù)量超過(guò)千萬(wàn)(雖然實(shí)際不太可能)
2、用戶表原來(lái)的名字叫做user_tab,我們切分為user_tab_0和user_tab_1(實(shí)際也可能不是這么隨意的名字),這樣就能把原來(lái)千萬(wàn)的數(shù)據(jù)分離成兩個(gè)百萬(wàn)的數(shù)據(jù)量的兩張表了。
3、如何操作這兩張表呢?我們利用userId也就是用戶的唯一標(biāo)識(shí)進(jìn)行區(qū)分。
4、userId%2 == 0的用戶操作表user_tab_0,同理userId%2 == 1的用戶操作表user_tab_1
5、那么在MyBatis中sql語(yǔ)句如何實(shí)現(xiàn)呢?下面是舉例查詢一個(gè)用戶的sql語(yǔ)句
<select id="getUser" parameterType="java.util.Map" resultType="UserDO">
SELECT userId, name
FROM user_tab_#{tabIndex}
WHERE userId = #{userId}
</select>
其中我們傳入了兩個(gè)參數(shù)tabIndex和userId,tabIndex就是需要操作表的標(biāo)示值(0或1),這樣如果需要查詢userId為5的用戶,那么最終出現(xiàn)的sql語(yǔ)句就會(huì)是:
SELECT userId, name FROM user_tab_1 WHERE userId = 5
其他多余的DAO服務(wù)和實(shí)現(xiàn)我這里就不多展示了,相信聰明的你肯定會(huì)的。
以上就是最簡(jiǎn)單的實(shí)現(xiàn),不需要多余的框架,不需要任何的插件也就滿足了分表的要求。
上面基本上就是所有實(shí)現(xiàn)的內(nèi)容了,下面就要開始詳細(xì)說(shuō)說(shuō)分離的細(xì)節(jié)了,看熱鬧的基本可以散了。
我將從下面幾個(gè)角度分別來(lái)說(shuō)說(shuō)。我盡可能用最簡(jiǎn)單的白話來(lái)說(shuō)。
分離的方式
切分的方式主要有兩種,水平切分和垂直切分。
1、水平切分
簡(jiǎn)單的說(shuō)就是,把一張表分離成幾張一模一樣的表,然后表的名字不同。就和上面最簡(jiǎn)單的例子一樣。
這種切分適合于一張表的數(shù)據(jù)量過(guò)大而導(dǎo)致操作時(shí)間變慢的情況,如保存的一些記錄表。
2、垂直切分
把不同的業(yè)務(wù)模塊分成不同的數(shù)據(jù)庫(kù),這些業(yè)務(wù)模塊直接最好是0耦合(簡(jiǎn)單的說(shuō)就是毫無(wú)關(guān)系)。
這主要是適合數(shù)據(jù)量普遍較大,而且業(yè)務(wù)場(chǎng)景比較分散,互相之間沒(méi)有邏輯關(guān)系的情況。
分離的策略
具體的策略有很多種,你也可以設(shè)計(jì)你自己的,普遍的策略有下面幾種,只是列舉就不具體展開了。
1、“%”取模,也就是上面例子中實(shí)現(xiàn)的,也是最簡(jiǎn)單的一種。
2、MD5哈希
3、移位
4、日期時(shí)間(根據(jù)不同的日期分表,如一個(gè)月一張表,這個(gè)月就操作這張表,下個(gè)月就下張表)
5、枚舉范圍(用戶1-10000操作第一張表,用戶10001-20000操作第二張表)
分離的問(wèn)題
下面說(shuō)說(shuō)最終要的點(diǎn),導(dǎo)致的問(wèn)題。
數(shù)據(jù)庫(kù)肯定不是你說(shuō)分就分的。(人家比較有感情的,怎么能說(shuō)分就分呢?)
正經(jīng)來(lái)說(shuō),我列舉了下面幾個(gè)分離只有會(huì)導(dǎo)致的問(wèn)題。
1、添加時(shí)主鍵唯一性的問(wèn)題;分離之后多張表,就會(huì)導(dǎo)致原有的自增長(zhǎng)主鍵不唯一,所以沒(méi)有辦法自增長(zhǎng)了,導(dǎo)致問(wèn)題,解決方案的也是有的,比如單獨(dú)維護(hù)一張主鍵表專門用來(lái)存放當(dāng)前主鍵,或者說(shuō)用別的中間件等。
2、新增時(shí)的效率問(wèn)題,雖然不是個(gè)大問(wèn)題,但是新增肯定會(huì)多了計(jì)算量嘛,這個(gè)問(wèn)題可以忽略不計(jì)。
3、查詢所帶來(lái)的分頁(yè)問(wèn)題,分離成多張表之后,分頁(yè)查詢就很困難了,這也考慮到不同的分離用不同的解決方案,總之會(huì)產(chǎn)生問(wèn)題。
4、同理,關(guān)聯(lián)查詢,原本一張表關(guān)聯(lián)別的表或者別的表關(guān)聯(lián)一張表,都很簡(jiǎn)單,但是現(xiàn)在分離之后就難了。
5、事務(wù)問(wèn)題,多張表需要使用分布式事務(wù)才能完成原來(lái)帶有事務(wù)的操作。因?yàn)樵瓉?lái)的事務(wù)只是鎖一張表現(xiàn)在可能要鎖多張了呢。
6、擴(kuò)展性問(wèn)題,有的切分策略下,對(duì)數(shù)據(jù)的擴(kuò)展性其實(shí)不好,之后如果有更多的數(shù)據(jù)來(lái)了,是說(shuō)還能再新建表來(lái)擴(kuò)展嗎?
分離的原則
下面總結(jié)了幾點(diǎn)分離的原則,主要是參考了網(wǎng)絡(luò)上的,沒(méi)有任何實(shí)際的依據(jù)(我也不是個(gè)年薪百萬(wàn)的DBA也碰不到那么大的數(shù)據(jù)去實(shí)際檢驗(yàn)嘛),所以如果有任何問(wèn)題也請(qǐng)指出。
1、能不分就不分
2、能分少就不分多
3、多冗余,不關(guān)聯(lián)
4、避免使用分布式事務(wù),主要是太難我也不會(huì)啊
5、單表千萬(wàn)記錄以內(nèi)就不分
6、現(xiàn)在不分以后分也來(lái)得及
7、擴(kuò)展,耦合,仔細(xì)考慮
實(shí)現(xiàn)分離的方式
最后說(shuō)說(shuō)分離的方式,現(xiàn)在流行使用的DAO框架是MyBatis,也有很多別的框架。分離的實(shí)現(xiàn)主要有下面幾種方式。
1、原生實(shí)現(xiàn),就和最上面的例子一樣,不需要其他任何的東西,利用原生的框架,自己去控制實(shí)現(xiàn)。
優(yōu)點(diǎn)是:容易控制,掌握主動(dòng)權(quán)。
缺點(diǎn)是:代碼量多,需要自己很清楚,修改不方便,不支持復(fù)雜的切分,比如切分之后還需要做一些分頁(yè)查詢,還有上面說(shuō)的主鍵問(wèn)題等。
2、插件實(shí)現(xiàn),利用框架本身開發(fā)的一些插件,去實(shí)現(xiàn)這些插件,然后利用插件去訪問(wèn)數(shù)據(jù)庫(kù),直接實(shí)現(xiàn)分離。
優(yōu)點(diǎn)是:代碼量少,實(shí)現(xiàn)簡(jiǎn)單,擴(kuò)展性好。
缺點(diǎn)是:不易控制,分離方式有限,出現(xiàn)問(wèn)題難以解決。沒(méi)有找到特別成熟的插件。
3、中間件實(shí)現(xiàn)。利用一些數(shù)據(jù)庫(kù)訪問(wèn)的中間件,在訪問(wèn)數(shù)據(jù)庫(kù)之前做一些操作使得sql進(jìn)行相應(yīng)的變化從而實(shí)現(xiàn)分離。
優(yōu)點(diǎn)是:耦合小,擴(kuò)展性好,可以解決分布式事務(wù)的問(wèn)題。
確定是:實(shí)現(xiàn)比較復(fù)雜,需要對(duì)中間件進(jìn)行學(xué)習(xí),成本較大。維護(hù)也是一個(gè)大問(wèn)題,萬(wàn)一掛掉了。。
總之方式各有千秋,但是考慮到成本上面,第一種幾乎是0成本,即可上手,而且比較容易控制,就如同最上面給出的例子一樣,而且當(dāng)前我處理的數(shù)據(jù)還沒(méi)有到達(dá)那種處處要分離的地步,所以我選擇第一種。也推薦使用。如果你找到比較好用的插件或者中間件也可以在評(píng)論中推薦。
總結(jié)
在實(shí)際項(xiàng)目中,我是因?yàn)橛脩舻馁~戶記錄過(guò)多所以不得不進(jìn)行分離,而且因?yàn)橘~戶記錄更多的只是新增沒(méi)有修改和刪除,查詢也是少數(shù),所以使用了最簡(jiǎn)單的方式進(jìn)行分離,也選擇了最簡(jiǎn)單的策略。希望上面的原則策略方式和問(wèn)題的總結(jié)能對(duì)你有所幫助,有所參考。如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
淺談升級(jí)Spring Cloud到Finchley后的一點(diǎn)坑
這篇文章主要介紹了淺談升級(jí)Spring Cloud到Finchley后的一點(diǎn)坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
Java 判斷兩個(gè)字符串是否由相同的字符組成的實(shí)例
今天小編就為大家分享一篇Java 判斷兩個(gè)字符串是否由相同的字符組成的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
SpringBoot之RestTemplate在URL中轉(zhuǎn)義字符的問(wèn)題
這篇文章主要介紹了SpringBoot之RestTemplate在URL中轉(zhuǎn)義字符的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
Java實(shí)現(xiàn)合并兩個(gè)有序序列算法示例
這篇文章主要介紹了Java實(shí)現(xiàn)合并兩個(gè)有序序列算法,簡(jiǎn)單描述了序列合并算法的原理與java合并有序序列的具體操作步驟及相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-09-09
Java使用JSQLParser解析和操作SQL的技術(shù)指南
在開發(fā)過(guò)程中,解析和操作?SQL?是一個(gè)常見的需求,JSQLParser?是一個(gè)強(qiáng)大的開源?Java?庫(kù),用于解析?SQL?并提供語(yǔ)法樹操作功能,本文將詳細(xì)介紹如何使用?JSQLParser,并提供常見使用場(chǎng)景的代碼示例,需要的朋友可以參考下2025-04-04
SpringBoot項(xiàng)目打包部署到Tomcat的操作流程
在最近一個(gè)項(xiàng)目中,維護(hù)行里一個(gè)年代較為久遠(yuǎn)的單體項(xiàng)目,需要將項(xiàng)目打包放到的tomcat服務(wù)器下運(yùn)行,所以本文就給大家介紹一下SpringBoot項(xiàng)目打包部署到Tomcat的流程步驟,需要的朋友可以參考下2023-08-08

