日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL分库分页_MySQL分库分表的分页查询解决方案

發布時間:2025/3/17 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL分库分页_MySQL分库分表的分页查询解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題的提出

我們知道,當我們的數據量達到一定數量時,需要將數據表進行水平拆分,從而滿足大量數據的存儲和查詢,保證系統的可用性,但同時會出現另外一個問題就是,如果業務要查詢“最近注冊的第3頁用戶”,該如何實現呢?單庫上,可以通過簡單的sql實現分頁查詢。

select * from t_user order by time limit 200,100

1

select *fromt_userorderbytimelimit200,100

分庫分表后變成兩個庫后,分庫依據是user_id,排序依據是time,單個分數據庫層失去了time排序的全局視野,如果同樣需要實現分頁查詢時該怎么辦呢?有什么比較好的MySQL分庫分表的分頁查詢解決方案呢?

全局視野法

正常來講,不管哪一個分庫的第3頁都不一定有全局第3頁的所有數據,例如一下三種情況:

情況一:兩個分庫按照時間排序,數據各占一半,則每頁取offset和limit的一般數據回來合并就可以了

情況二:所有數據都在一個庫上,則取一個庫的所有數據回來就可以了

情況三,那么一般情況是,每個分庫的數據數據是隨機的,但是一定是在全局offset=600之內

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

這種方法缺點是:當查詢的頁數增大時,每個分庫所需返回的數據也越來成倍增加,降低了查詢的性能

業務折中

第一種折中的方案是

對全局視野法的一種優化,即禁用制定頁數的分頁查詢,必須通過下一頁來實現分頁查詢的頁數跳轉,并且在每次查詢下一頁時將上一頁的最大排序字段的值帶上(這里就是時間time),這樣在每個分庫查詢數據時待上這個條件,可以優化查詢速率。

第二種折中的方案是

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

使用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,注意這里的500=1000/分表數量,并將這個sql下發至每個分庫分表中執行,每個分庫返回這個sql執行的結果。

2. 找到所有分庫返回結果的time的最小值

第一個庫,5條數據的time最小值是1487501123

第二個庫,5條數據的time最小值是1487501223

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

3. 查詢二次改寫

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

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

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

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

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

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

從上面圖片可以看出,DB1比第一次查出來的數據多了兩行,應為查詢的范圍擴大了

4. 計算time_min這條記錄在全局的offset

根據第一步查詢的sqlselect * from T order by time offset 500 limit ,我們知道每個庫的offset值了,將DB0中的最小time的數據虛擬到DB1中推算在DB1中的offset值=497

從而我們得知time_min這條記錄在全局的offset值=500+497=997

5. 根據第二次查詢出來的結果集,在內存中作排序,已知time_min在全局中的offset=997,那么結果集排序之后也能推算出offset=1000所在的記錄,從而獲得sqlselect * from T order by time offset 1000 limit 5的分頁查詢記錄(圖片黃色部分)

總結:可以精確的返回業務所需數據,每次返回的數據量都非常小,不會隨著翻頁增加數據的返回量。

瀏覽量:

7

0

總結

以上是生活随笔為你收集整理的MySQL分库分页_MySQL分库分表的分页查询解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。