{eval=Array;=+count(Array);}

国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

問答專欄Q & A COLUMN

分庫(kù)分表的幾種常見玩法及如何解決跨庫(kù)查詢問題?

mykurisumykurisu 回答0 收藏1
收藏問題

1條回答

philadelphia

philadelphia

回答于2022-06-28 14:57

在現(xiàn)在的互聯(lián)網(wǎng)架構(gòu)中,分庫(kù)分表是一種非常常見的手段,主要用于解決單表或者單庫(kù)數(shù)據(jù)過(guò)多而導(dǎo)致的性能問題。

通常,我們分庫(kù)有水平切分和垂直切分兩種方式

垂直切分在我們的微服務(wù)架構(gòu)中很常見,將數(shù)據(jù)庫(kù)根據(jù)業(yè)務(wù)模塊進(jìn)行拆分,業(yè)務(wù)的邏輯處理都通過(guò)服務(wù)調(diào)用來(lái)進(jìn)行,而不是將邏輯放在數(shù)據(jù)層面,這樣就能降低數(shù)據(jù)庫(kù)表與表之間的耦合度。

而水平切分,就是我們通常用來(lái)解決數(shù)據(jù)問題的手段了。將數(shù)據(jù)庫(kù)中單表的數(shù)據(jù)進(jìn)行切分,分成多張相同的表單,數(shù)據(jù)按照一定的規(guī)則分布到不同的數(shù)據(jù)庫(kù)實(shí)例中,從而達(dá)到降低數(shù)據(jù)量、提高性能的目的。

而水平切分,就需要有分庫(kù)的依據(jù)

使用哪個(gè)字段來(lái)作為分庫(kù)的依據(jù)呢?

通常情況下,我們會(huì)選擇主鍵作為分庫(kù)的依據(jù),根據(jù)一定的算法,將數(shù)據(jù)均勻的分布到每個(gè)數(shù)據(jù)庫(kù)實(shí)例中,同時(shí),盡量讓請(qǐng)求也均勻的分布到每個(gè)數(shù)據(jù)庫(kù)實(shí)例上。

例如:我們將訂單表進(jìn)行了切分,一分為二(DB1、BD2),訂單表的主鍵就是訂單ID,我們想要均勻的分布數(shù)據(jù)的話,我們可以對(duì)訂單ID進(jìn)行判斷,是單數(shù),我們就放在DB1中,是雙數(shù),我們就放到DB2中,這樣,我們的數(shù)據(jù)分布就非常的平均,同時(shí),我們的請(qǐng)求在概率上,也是平均的。

當(dāng)然,分庫(kù)依據(jù)可以很多,這個(gè)可以根據(jù)自己的業(yè)務(wù)場(chǎng)景進(jìn)行設(shè)置,只要明白,我們分庫(kù)是為了緩解數(shù)據(jù)庫(kù)的壓力,降低單表的數(shù)據(jù)量,如果我們分庫(kù)以后,DB1的數(shù)據(jù)量和請(qǐng)求數(shù)遠(yuǎn)大于DB2,那么我們分庫(kù)的意義就不是很大了。

而分庫(kù)以后,最難解決的就是分頁(yè)查詢的問題

通常情況下,我們的分頁(yè)查詢都是通過(guò)時(shí)間維度進(jìn)行排序的。如以下sql:

select * from T order by time offset X limit Y;

但是,分庫(kù)以后,不同的數(shù)據(jù)庫(kù)如何進(jìn)行查詢排序呢?我們就來(lái)說(shuō)一跨庫(kù)的分頁(yè)查詢方式。

全局視野方式

假設(shè),我們現(xiàn)在要查詢某張表的第三頁(yè)數(shù)據(jù),每頁(yè)100條數(shù)據(jù),曾經(jīng)沒有分庫(kù)的時(shí)候,我們只需要

select * from T order by time offset 200 limit 100;

但是,分庫(kù)以后,這第三頁(yè)的100條數(shù)據(jù)就有很多種分布方式了。

1)均勻分布(極端情況)

數(shù)據(jù)非常均勻的分布在兩個(gè)庫(kù)中,想要找到第三頁(yè)的數(shù)據(jù),就在兩個(gè)庫(kù)中各取50%就好了。

2)全部來(lái)自一個(gè)庫(kù)(極端情況)

數(shù)據(jù)非常不平均的分配到了一個(gè)庫(kù)中,所有的數(shù)據(jù)都來(lái)至于一個(gè)庫(kù),也就是說(shuō),只需要取這個(gè)單庫(kù)的數(shù)據(jù)就可以了。

3)散亂分布(通常情況)

這種情況下,我們很難知道,第三頁(yè)的數(shù)據(jù)應(yīng)該在不同的庫(kù)中從第幾條開始取數(shù),因?yàn)榉謳?kù)后,我們丟失了全局視野。因此,如果我們想要精準(zhǔn)的找到目標(biāo)數(shù)據(jù),就必須重新構(gòu)建全局的視野。

如何重新構(gòu)建這種全局視野呢?

還是用我們要查詢第三頁(yè)的數(shù)據(jù)來(lái)舉例,我們可以將兩個(gè)庫(kù)中的第一到第三頁(yè)的數(shù)據(jù)全部查詢出來(lái),然后在內(nèi)存中合并后進(jìn)行排序,再取出第三頁(yè)的數(shù)據(jù)。

我們的sql也就發(fā)生了變化,從

select * from T order by time offset 200 limit 100;

改為

select * from T order by time offset 0 limit 100+200;

全局視野方式進(jìn)行查詢的好處很明顯,就是能夠讓業(yè)務(wù)數(shù)據(jù)絕對(duì)精準(zhǔn)的返回。但是缺點(diǎn)也是明顯,數(shù)據(jù)的查詢量大,而且消耗的內(nèi)存資源較多,當(dāng)頁(yè)碼增大的時(shí)候,性能會(huì)集聚的下降。

如果想要解決全局視野方式的缺點(diǎn),我們可以做出交互上的一點(diǎn)小犧牲來(lái)實(shí)現(xiàn)

禁止跳轉(zhuǎn)頁(yè)方式

相信這個(gè)分頁(yè)方式大家都不陌生,但是,這種分頁(yè)方式確實(shí)讓我們分庫(kù)以后的查詢難度幾何級(jí)的提升,如果想要解決跨頁(yè)查詢的問題,我們可以對(duì)我們的分頁(yè)控件進(jìn)行優(yōu)化,只保留“上一下”、“下一頁(yè)”的功能,去掉跳轉(zhuǎn)頁(yè)的功能。

當(dāng)禁止跳頁(yè)以后,我們每次查詢后,就能夠得到當(dāng)頁(yè)最后一次查詢結(jié)果的時(shí)間,我們要查詢一個(gè)分頁(yè)中的記錄時(shí),是需要查詢大于當(dāng)前時(shí)間的100條記錄就可以了。

兩個(gè)數(shù)據(jù)庫(kù)中各取100條,然后再匯總排序,這樣就能夠大大的提升查詢的效率,同時(shí)也保證了數(shù)據(jù)的精準(zhǔn)。

我們的sql也就改成了

select * from T order by time where time>@preMaxTime limit 100;

使用此方式,我們就不會(huì)因?yàn)轫?yè)碼增加而出現(xiàn)性能的下降了,只是用戶的交互體驗(yàn)會(huì)稍差一些了。當(dāng)然,如果是APP用戶,就不用擔(dān)心這點(diǎn)了,因?yàn)锳PP用戶很少使用跳轉(zhuǎn)頁(yè)的交互方式。

允許精度損失方式

允許精度損失的方式就比較暴力,我們不去管數(shù)據(jù)的分布問題,只是單純的每個(gè)庫(kù)中取出50條數(shù)據(jù),然后排序展示。

在業(yè)務(wù)中,可能會(huì)出現(xiàn)第二頁(yè)的部分?jǐn)?shù)據(jù)時(shí)間上早于第一頁(yè)的數(shù)據(jù),這主要還是根據(jù)我們的保存數(shù)據(jù)時(shí)候分分布情況來(lái)決定。如果我們存儲(chǔ)數(shù)據(jù)的時(shí)候,分布得越平均,這種查詢方式得到的結(jié)果自然就越精準(zhǔn)。

使用這種方式,我們就不需要考慮性能上的問題,也不需要考慮頁(yè)面跳轉(zhuǎn)和頁(yè)碼的問題,查詢的復(fù)雜度是最低的,是比較推薦的一種查詢方式。

當(dāng)然,如果你的業(yè)務(wù)不允許這樣的情況出現(xiàn),還需要滿足交互、效率等等各種需求,那么,就只有使用最后一個(gè)方式了。

二次查詢方式

這可以說(shuō)是解決分庫(kù)查詢的究極武器了,能夠保證數(shù)據(jù)的精準(zhǔn)度、查詢的效率、用戶的交互頁(yè)面,犧牲的只是小小的性能開銷和一些代碼難度的上升。

方式其實(shí)也不難,假設(shè)我們要查詢第21頁(yè)的數(shù)據(jù),每頁(yè)5條。這個(gè)時(shí)候,我們先假設(shè)數(shù)據(jù)是平均分布的,但是我們?cè)诿總€(gè)庫(kù)都查詢?nèi)康?條數(shù)據(jù)。也就是:

select * from T order by time offset 100 limit 5;

這時(shí),我們得到的數(shù)據(jù)可能是這樣的。

而兩個(gè)DB中,最小的時(shí)間是1487500001【minTime】,這個(gè)時(shí)間記錄下來(lái)。兩個(gè)DB中各自的最大時(shí)間也記錄下來(lái),分別是DB1:1487500041【maxTime1】 和 DB2:1487500061【maxTime2】。

這時(shí),我們?cè)谑褂脮r(shí)間去兩個(gè)數(shù)據(jù)庫(kù)中再次進(jìn)行查詢。

select * from T where time between minTime and maxTime1 order by time;
select * from T where time between minTime and maxTime2 order by time;

由于之前minTime來(lái)自于DB1,因此,DB1的數(shù)據(jù)不會(huì)發(fā)生變化,但是DB2中的條件被放寬了,因此可能會(huì)查詢出更多的數(shù)據(jù)。結(jié)果可能如下:

而兩個(gè)結(jié)果集合并以后,相當(dāng)于就獲得了全局視野,也就可以很容易的找出這一頁(yè)需要的5條數(shù)據(jù)了。

如果誰(shuí)還有更好的分庫(kù)分頁(yè)查詢的方法,也歡迎指教!

評(píng)論0 贊同0
  •  加載中...

最新活動(dòng)

您已邀請(qǐng)0人回答 查看邀請(qǐng)

我的邀請(qǐng)列表

  • 擅長(zhǎng)該話題
  • 回答過(guò)該話題
  • 我關(guān)注的人
向幫助了您的網(wǎng)友說(shuō)句感謝的話吧!
付費(fèi)偷看金額在0.1-10元之間
<