国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

業界難題-“跨庫分頁”的四種方案

開發 開發工具
今天給大家分享一下關于業界難題-“跨庫分頁”的四種方案。

[[184348]]

一、需求緣起

1. 分頁需求

互聯網很多業務都有分頁拉取數據的需求,例如:

(1)微信消息過多時,拉取第N頁消息

(2)京東下單過多時,拉取第N頁訂單

(3)瀏覽58同城,查看第N頁帖子

這些業務場景對應的消息表,訂單表,帖子表分頁拉取需求有這樣一些特點:

(1)有一個業務主鍵id, 例如msg_id, order_id, tiezi_id

(2)分頁排序是按照非業務主鍵id來排序的,業務中經常按照時間time來排序order by

在數據量不大時,可以通過在排序字段time上建立索引,利用SQL提供的offset/limit功能就能滿足分頁查詢需求:

  1. select * from t_msg order by time offset 200 limit 100 
  2. select * from t_order order by time offset 200 limit 100 
  3. select * from t_tiezi order by time offset 200 limit 100 

此處假設一頁數據為100條,均拉取第3頁數據。

2. 分庫需求

高并發大流量的互聯網架構,一般通過服務層來訪問數據庫,隨著數據量的增大,數據庫需要進行水平切分,分庫后將數據分布到不同的數據庫實例(甚至物理機器)上,以達到降低數據量,增加實例數的擴容目的。

一旦涉及分庫,逃不開“分庫依據”patition key的概念,使用哪一個字段來水平切分數據庫呢:大部分的業務場景,會使用業務主鍵id。

確定了分庫依據patition key后,接下來要確定的是分庫算法:大部分的業務場景,會使用業務主鍵id取模的算法來分庫,這樣即能夠保證每個庫的數據分布是均勻的,又能夠保證每個庫的請求分布是均勻的,實在是簡單實現負載均衡的好方法,此法在互聯網架構中應用頗多。

舉一個更具體的例子:

用戶庫user,水平切分后變為兩個庫

用戶庫user,水平切分后變為兩個庫,分庫依據patition key是uid,分庫算法是uid取模:uid%2余0的數據會落到db0,uid%2余1的數據會落到db1。

3. 問題的提出

仍然是上述用戶庫的例子,如果業務要查詢“最近注冊的第3頁用戶”,該如何實現呢?單庫上,可以

select * from t_user order by time offset 200 limit 100

變成兩個庫后,分庫依據是uid,排序依據是time,數據庫層失去了time排序的全局視野,數據分布在兩個庫上,此時該怎么辦呢?

如何滿足“跨越多個水平切分數據庫,且分庫依據與排序依據為不同屬性,并需要進行分頁”的查詢需求,實現 select * from T order by time offset X limit Y的跨庫分頁SQL,是本文將要討論的技術問題。

二、全局視野法

服務層通過uid取模將數據分布到兩個庫上

如上圖所述,服務層通過uid取模將數據分布到兩個庫上去之后,每個數據庫都失去了全局視野,數據按照time局部排序之后,不管哪個分庫的第3頁數據,都不一定是全局排序的第3頁數據。

那到底哪些數據才是全局排序的第3頁數據呢,暫且分三種情況討論。

1. 極端情況,兩個庫的數據完全一樣

兩個庫的數據完全一樣

如果兩個庫的數據完全相同,只需要每個庫offset一半,再取半頁,就是最終想要的數據(如上圖中粉色部分數據)。

2. 極端情況,結果數據來自一個庫

結果數據來自一個庫

也可能兩個庫的數據分布及其不均衡,例如db0的所有數據的time都大于db1的所有數據的time,則可能出現:一個庫的第3頁數據,就是全局排序后的第3頁數據(如上圖中粉色部分數據)。

3. 一般情況,每個庫數據各包含一部分

每個庫數據各包含一部分

正常情況下,全局排序的第3頁數據,每個庫都會包含一部分(如上圖中粉色部分數據)。

由于不清楚到底是哪種情況,所以必須每個庫都返回3頁數據,所得到的6頁數據在服務層進行內存排序,得到數據全局視野,再取第3頁數據,便能夠得到想要的全局分頁數據。

再總結一下這個方案的步驟:

(1)將order by time offset X limit Y,改寫成order by time offset 0 limit X+Y

(2)服務層將改寫后的SQL語句發往各個分庫:即例子中的各取3頁數據

(3)假設共分為N個庫,服務層將得到N*(X+Y)條數據:即例子中的6頁數據

(4)服務層對得到的N*(X+Y)條數據進行內存排序,內存排序后再取偏移量X后的Y條記錄,就是全局視野所需的一頁數據

4. 方案優點:通過服務層修改SQL語句,擴大數據召回量,能夠得到全局視野,業務無損,精準返回所需數據。

5. 方案缺點(顯而易見):

(1)每個分庫需要返回更多的數據,增大了網絡傳輸量(耗網絡);

(2)除了數據庫按照time進行排序,服務層還需要進行二次排序,增大了服務層的計算量(耗CPU);

(3)最致命的,這個算法隨著頁碼的增大,性能會急劇下降,這是因為SQL改寫后每個分庫要返回X+Y行數據:返回第3頁,offset中的X=200;假如要返回第100頁,offset中的X=9900,即每個分庫要返回100頁數據,數據量和排序量都將大增,性能平方級下降。

三、業務折衷法

“全局視野法”雖然性能較差,但其業務無損,數據精準,不失為一種方案,有沒有性能更優的方案呢?

“任何脫離業務的架構設計都是耍流氓”,技術方案需要折衷,在技術難度較大的情況下,業務需求的折衷能夠極大的簡化技術方案。

1. 業務折衷一:禁止跳頁查詢

在數據量很大,翻頁數很多的時候,很多產品并不提供“直接跳到指定頁面”的功能,而只提供“下一頁”的功能,這一個小小的業務折衷,就能極大的降低技術方案的復雜度。

不夠跳頁,那么第一次只能夠查第一頁

如上圖,不夠跳頁,那么第一次只能夠查第一頁:

(1)將查詢order by time offset 0 limit 100,改寫成order by time where time>0 limit 100

(2)上述改寫和offset 0 limit 100的效果相同,都是每個分庫返回了一頁數據(上圖中粉色部分);

每個分庫返回了一頁數據

(3)服務層得到2頁數據,內存排序,取出前100條數據,作為最終的第一頁數據,這個全局的第一頁數據,一般來說每個分庫都包含一部分數據(如上圖粉色部分);

咦,這個方案也需要服務器內存排序,豈不是和“全局視野法”一樣么?第一頁數據的拉取確實一樣,但每一次“下一頁”拉取的方案就不一樣了。

點擊“下一頁”時,需要拉取第二頁數據,在第一頁數據的基礎之上,能夠找到第一頁數據time的最大值:

這個上一頁記錄的time_max,會作為第二頁數據拉取的查詢條件:

(1)將查詢order by time offset 100 limit 100,改寫成order by time where time>$time_max limit 100

(2)這下不是返回2頁數據了(“全局視野法,會改寫成offset 0 limit 200”),每個分庫還是返回一頁數據(如上圖中粉色部分);

(3)服務層得到2頁數據,內存排序,取出前100條數據,作為最終的第2頁數據,這個全局的第2頁數據,一般來說也是每個分庫都包含一部分數據(如上圖粉色部分);

如此往復,查詢全局視野第100頁數據時,不是將查詢條件改寫為offset 0 limit 9900+100(返回100頁數據),而是改寫為time>$time_max99 limit 100(仍返回一頁數據),以保證數據的傳輸量和排序的數據量不會隨著不斷翻頁而導致性能下降。

2. 業務折衷二:允許數據精度損失

“全局視野法”能夠返回業務無損的精確數據,在查詢頁數較大,例如第100頁時,會有性能問題,此時業務上是否能夠接受,返回的100頁不是精準的數據,而允許有一些數據偏差呢?

數據庫分庫-數據均衡原理

使用patition key進行分庫,在數據量較大,數據分布足夠隨機的情況下,各分庫所有非patition key屬性,在各個分庫上的數據分布,統計概率情況是一致的。

例如,在uid隨機的情況下,使用uid取模分兩庫,db0和db1:

(1)性別屬性,如果db0庫上的男性用戶占比70%,則db1上男性用戶占比也應為70%

(2)年齡屬性,如果db0庫上18-28歲少女用戶比例占比15%,則db1上少女用戶比例也應為15%

(3)時間屬性,如果db0庫上每天10:00之前登錄的用戶占比為20%,則db1上應該是相同的統計規律

利用這一原理,要查詢全局100頁數據,offset 9900 limit 100改寫為offset 4950 limit 50,每個分庫偏移4950(一半),獲取50條數據(半頁),得到的數據集的并集,基本能夠認為,是全局數據的offset 9900 limit 100的數據,當然,這一頁數據的精度,并不是精準的。

根據實際業務經驗,用戶都要查詢第100頁網頁、帖子、郵件的數據了,這一頁數據的精準性損失,業務上往往是可以接受的,但此時技術方案的復雜度便大大降低了,既不需要返回更多的數據,也不需要進行服務內存排序了。

四、終極武器-二次查詢法

有沒有一種技術方案,即能夠滿足業務的精確需要,無需業務折衷,又高性能的方法呢?這就是接下來要介紹的終極武器:“二次查詢法”。

為了方便舉例,假設一頁只有5條數據,查詢第200頁的SQL語句為select * from T order by time offset 1000 limit 5;

1. 步驟一:查詢改寫

將select * from T order by time offset 1000 limit 5

改寫為select * from T order by time offset 500 limit 5

并投遞給所有的分庫,注意,這個offset的500,來自于全局offset的總偏移量1000,除以水平切分數據庫個數2。

如果是3個分庫,則可以改寫為select * from T order by time offset 333 limit 5

假設這三個分庫返回的數據(time, uid)如下:

三個分庫返回的數據(time, uid)如下

可以看到,每個分庫都是返回的按照time排序的一頁數據。

2. 步驟二:找到所返回3頁全部數據的最小值

  • 第一個庫,5條數據的time最小值是1487501123
  • 第二個庫,5條數據的time最小值是1487501133
  • 第三個庫,5條數據的time最小值是1487501143

故,三頁數據中,time最小值來自第一個庫,time_min=1487501123,這個過程只需要比較各個分庫第一條數據,時間復雜度很低

3. 步驟三:查詢二次改寫

第一次改寫的SQL語句是select * from T order by time offset 333 limit 5

第二次要改寫成一個between語句,between的起點是time_min,between的終點是原來每個分庫各自返回數據的最大值:

第一個分庫,第一次返回數據的最大值是1487501523

所以查詢改寫為select * from T order by time where time between time_min and 1487501523

第二個分庫,第一次返回數據的最大值是1487501323

所以查詢改寫為select * from T order by time where time between time_min and 1487501323

第三個分庫,第一次返回數據的最大值是1487501553

所以查詢改寫為select * from T order by time where time between time_min and 1487501553

相對第一次查詢,第二次查詢條件放寬了,故第二次查詢會返回比第一次查詢結果集更多的數據,假設這三個分庫返回的數據(time, uid)如下:

可以看到:

  • 由于time_min來自原來的分庫一,所以分庫一的返回結果集和第一次查詢相同(所以其實這次訪問是可以省略的);
  • 分庫二的結果集,比第一次多返回了1條數據,頭部的1條記錄(time最小的記錄)是新的(上圖中粉色記錄);
  • 分庫三的結果集,比第一次多返回了2條數據,頭部的2條記錄(time最小的2條記錄)是新的(上圖中粉色記錄);

4. 步驟四:在每個結果集中虛擬一個time_min記錄,找到time_min在全局的offset

在第一個庫中,time_min在第一個庫的offset是333

在第二個庫中,(1487501133, uid_aa)的offset是333(根據第一次查詢條件得出的),故虛擬time_min在第二個庫的offset是331

在第三個庫中,(1487501143, uid_aaa)的offset是333(根據第一次查詢條件得出的),故虛擬time_min在第三個庫的offset是330

綜上,time_min在全局的offset是333+331+330=994

5. 步驟五:既然得到了time_min在全局的offset,就相當于有了全局視野,根據第二次的結果集,就能夠得到全局offset 1000 limit 5的記錄

第二次查詢在各個分庫返回的結果集是有序的,又知道了time_min在全局的offset是994,一路排下來,容易知道全局offset 1000 limit 5的一頁記錄(上圖中黃色記錄)。

是不是非常巧妙?這種方法的優點是:可以精確的返回業務所需數據,每次返回的數據量都非常小,不會隨著翻頁增加數據的返回量。

不足是:需要進行兩次數據庫查詢。

五、總結

今天介紹了解決“跨N庫分頁”這一難題的四種方法:

1. 方法一:全局視野法

(1)將order by time offset X limit Y,改寫成order by time offset 0 limit X+Y

(2)服務層對得到的N*(X+Y)條數據進行內存排序,內存排序后再取偏移量X后的Y條記錄

這種方法隨著翻頁的進行,性能越來越低。

2. 方法二:業務折衷法-禁止跳頁查詢

(1)用正常的方法取得第一頁數據,并得到第一頁記錄的time_max

(2)每次翻頁,將order by time offset X limit Y,改寫成order by time where time>$time_max limit Y

以保證每次只返回一頁數據,性能為常量。

3. 方法三:業務折衷法-允許模糊數據

(1)將order by time offset X limit Y,改寫成order by time offset X/N limit Y/N

4. 方法四:二次查詢法

(1)將order by time offset X limit Y,改寫成order by time offset X/N limit Y

(2)找到最小值time_min

(3)between二次查詢,order by time between $time_min and $time_i_max

(4)設置虛擬time_min,找到time_min在各個分庫的offset,從而得到time_min在全局的offset

(5)得到了time_min在全局的offset,自然得到了全局的offset X limit Y

【本文為51CTO專欄作者“58沈劍”原創稿件,轉載請聯系原作者】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2019-05-14 14:27:21

跨庫分頁分庫數據

2024-05-22 19:10:18

跨域Web開發

2024-09-26 14:27:14

2025-01-20 15:50:19

2025-05-09 09:39:45

2025-12-17 08:09:43

2025-02-18 16:27:01

2023-02-03 08:47:20

職位招聘難題

2025-01-06 08:33:10

2023-08-26 20:08:15

分庫分表Spring

2023-12-11 11:00:39

云原生CIO數字化

2025-06-09 09:31:22

2023-05-30 08:38:25

MySQL數據庫日志

2025-01-15 12:43:23

2021-08-25 12:55:33

Linuxcron

2013-07-26 16:38:54

OpenStackHadoop

2010-01-12 12:15:25

SOA安全解決方案

2020-04-07 10:05:34

React開發工具

2018-01-03 08:52:27

MySQL數據庫級別

2011-03-14 13:33:32

Oracle數據庫啟動
點贊
收藏

51CTO技術棧公眾號

青青草原亚洲| 小草av在线播放| 亚洲综合清纯丝袜自拍| 懂色av色香蕉一区二区蜜桃| 黄色99视频| 午夜激情一区二区| 性欧美freehd18| 91香蕉亚洲精品| 亚洲午夜久久久久久久久电影网 | 欧美激情精品久久久久久久变态 | 免费不卡视频| 欧美一区二区三区四区五区六区| 色综合视频一区二区三区高清| 1024精品久久久久久久久| 久久精品丝袜高跟鞋| 亚洲va国产va欧美va观看| 偷拍亚洲精品| 色视频在线观看免费| 欧美日韩精品中文字幕一区二区| 日韩欧美在线网站| 免费成人美女在线观看.| 一级毛片aaaaaa免费看| 国产女人水真多18毛片18精品| 日韩午夜精品视频| 成人亚洲一区二区一| 国产精品嫩模av在线| 黄色在线免费看| 精品一区久久久久久| 亚洲最大在线视频| 久久国产精品99久久久久久老狼| 日韩电影毛片| 日韩视频在线免费播放| 欧美激情一二区| 欧美日韩免费网站| 日韩vs国产vs欧美| 99这里只有精品视频| 美女av电影| 国产精品国产三级国产专播精品人| 成人午夜视频免费看| 国产一区二区主播在线| 中文字幕亚洲精品视频| 欧美在线观看视频免费| 成人国产精品一区| 国产一区二区三区在线看 | 最新中文字幕久久| 国产精品mp4| 精品免费一区二区三区| 亚洲综合丝袜美腿| 国产老肥熟一区二区三区| 久久99久久人婷婷精品综合 | 高清在线观看免费| 成人黄色在线免费| 日韩在线中文视频| 精品剧情在线观看| 在线视频欧美精品| 亚洲另类一区二区| av色综合久久天堂av综合| 美女精品一区| 国产精品99一区二区| 精品毛片免费观看| 亚洲精品黑牛一区二区三区| 亚洲免费视频一区二区三区| 日本a级片久久久| 91中文精品字幕在线视频| www.日韩系列| 这里只有精品在线播放| 日韩高清人体午夜| 亚洲成色777777女色窝| 欧美成人一区二区三区片免费| 色欧美88888久久久久久影院| 亚洲大片在线观看| 一区二区免费视频| 亚洲v日本v欧美v久久精品| 亚洲图片有声小说| 亚洲6080在线| 精品女同一区二区三区在线播放| 亚洲国产综合在线| 色综合天天综合网国产成人综合天| 亚洲成av人片观看| 在线观看免费视频综合| 日韩欧美精品中文字幕| 一本到三区不卡视频| 富二代精品短视频| 制服丝袜亚洲色图| 欧美性受xxxx| 亚洲精品一区二区在线| 欧美午夜片欧美片在线观看| 精品精品国产高清a毛片牛牛| av亚洲精华国产精华精华| 丁香激情综合国产| 国产精品久久久久影院老司| 亚洲尤物在线视频观看| 国产日韩欧美制服另类| 国产乱码字幕精品高清av| 成人免费福利片| 成人激情校园春色| 美女黄网久久| 亚洲在线电影| 国产二区国产一区在线观看| 美女网站久久| 欧美一级视频| 国产精品一区专区| 国产色产综合产在线视频 | 色呦呦在线播放| 麻豆视频在线观看免费网站| 免费毛片在线| 亚洲美女尤物影院| 亚洲精品3区| 青草国产精品久久久久久| 不卡电影免费在线播放一区| 一色桃子久久精品亚洲| 欧美视频在线视频| 日韩在线免费视频观看| 国产v综合v亚洲欧美久久| 久久久精品2019中文字幕神马| 日韩在线观看免费| 91po在线观看91精品国产性色| 欧美老女人性生活| 成人亚洲欧美一区二区三区| 成人毛片100部免费看| 暖暖视频在线免费观看| 18av在线播放| japanese23hdxxxx日韩| 精品久久国产一区| 欧美三级不卡| 国产一区二区三区综合| 色天天综合久久久久综合片| 91麻豆精品国产综合久久久久久| 亚洲成年人在线播放| 国产精品老女人精品视频| 92看片淫黄大片看国产片| 91影视免费在线观看| jizzjizzjizz亚洲| 亚洲国产伊人| 日本人妖一区二区| 亚洲三级小视频| 在线色欧美三级视频| 日韩精品一线二线三线| 天堂中文资源在线| 99精品在免费线中文字幕网站一区| 伊人激情综合| 久久精品一级爱片| 欧美视频自拍偷拍| 久久精品国产亚洲7777| 国产精品视频区| 粉嫩粉嫩芽的虎白女18在线视频| 久久伊人精品| 国产美女性感在线观看懂色av| 99久久这里有精品| 99久久国产综合精品麻豆| 色香阁99久久精品久久久| 香蕉视频在线网址| 久久天天久久| 久久九九影视网| 日本久久久久久久| 邻家有女韩剧在线观看国语| 在线观看av每日更新免费| 欧美片第1页综合| 色综合天天在线| 久久国产精品99久久久久久丝袜 | 午夜影院韩国伦理在线| 日韩中文字幕区一区有砖一区 | 国产成人精品视频在线| 亚洲bt欧美bt日本bt| 日韩视频第二页| 污视频网站在线观看| 日本免费久久| 视频一区二区不卡| 国产一区二区三区美女| 中文字幕 久热精品 视频在线 | 我不卡手机影院| 久久久久国产精品麻豆ai换脸| 91精品国产一区二区三区香蕉| 国产日韩欧美另类| 白浆在线视频| 精彩视频一区二区三区| 亚洲福利在线看| 中文字幕精品一区日韩| eeuss鲁一区二区三区| 乱码第一页成人| 精品不卡在线视频| 国产精品igao激情视频| 欧美日韩国产观看视频| 懂色中文一区二区在线播放| 一区二区在线视频播放| 免费在线精品视频| 欧美孕妇性xxxⅹ精品hd| 久久精品国产大片免费观看| 色综合久久中文综合久久97| 91久久精品一区二区别| 成午夜精品一区二区三区软件| 亚洲成人tv网| 蜜桃视频在线观看成人| 动漫一区在线| 不卡区在线中文字幕| 91高清免费视频| 日本中文在线| 久久久久青草大香线综合精品| 亚洲18私人小影院| gratisvideos另类灌满|