分庫分表後的分頁查詢

程式設計師的貓發表於2021-04-25

假設有一張使用者表,經過分庫分表之後,現在均勻分佈在2臺伺服器。每個伺服器2張表

  1. 全域性視野法:因為不清楚按照時間排序之後的第三頁資料到底是如何分佈在資料庫上的,所以必須每個庫都返回3頁資料,所得到的6頁資料在服務層進行記憶體排序,得到全域性視野,再取第3頁資料。

    優點:通過服務層修改,擴大資料查詢量,得到全域性視野,業務無損,精確

    缺點(顯而易見):每個分庫都需要返回更多的資料,增大網路傳輸量;除了資料庫要按照time排序,服務層也需要二次排序,損耗效能;隨著頁碼的增大,效能極具下降,資料量和排序量都將大增,效能平方級下降。

   2. 業務折中

    2.1 禁止跳頁查詢,不提供“直接跳到指定頁面”的功能,只提供下一頁的功能。極大的降低技術方案的複雜度。第一頁的選取方法和全域性視野法一樣,但是點選下一頁時:

      2.1.1先找到上一頁的time的最大值,作為第二頁資料拉去的查詢條件,只取每頁的記錄數,

      2.2.2這樣服務層還是獲得兩頁資料,再做一次排序,獲取一頁資料。

      2.2.3改進了不會因為頁碼增大而導致資料的傳輸量和排序量增大

   3. 允許資料精度丟失:需要考慮業務員上是否接受在頁碼較大是返回的資料不是精準的資料。

    3.1在資料量較大,且ID對映分佈足夠隨機的話,應該是滿足等概率分佈的情況的,所以取一頁資料,我們在每個資料庫中取前半頁。

    3.2當然這樣的到的結果並不是精準的,但是當實際業務可以接受的話, 此時的技術方案的複雜度變大大降低。也不需要服務層記憶體排序了。

   4. 二次查詢法:既滿足業務的精確需求,也無需業務折中。現在假設每頁顯示10條資料,要查第三頁,資料分了兩個庫。 正常的語句是 select * from table order by time offset 20 limit 10,取偏移20個之後的10個

    4.1首次查詢查詢每個庫的select * from table order by time offset 10 limit 10;得到10條資料。這裡的offset是總offset/分庫數

    4.2 服務層得到來自兩個分庫的結果集,得到最小的time,也就是最頂層的time,這個time滿足最少有10條記錄在它前面,然後分別記錄每個庫的最大time

    4.3 分別再次查詢最小time->每個庫上一次的最大time的資料,得到每個庫的查詢結果

    4.4 在每個集合的最小time都是相同的,所以可以得到該最小time在整個資料庫中的offset,加起來就是這個最小time在全域性庫的offset位置。

    4.5 再將第二次查詢的結果集拼起來和得到的最小time的offset,推匯出 offset 20 limit 10的一頁記錄。

    優點:可以精確得到業務資料,且每次返回的資料量都非常小,不會隨著頁碼增加而資料量增大。

    缺點:需要進行兩次資料庫查詢

  5.通過額外的新增一張關聯表,屬性中必有id屬性,至於是否有庫id屬性和表id屬性(既第幾個庫和第幾個表)可有可無,因為這個可以根據id自行取模獲取,注意這張表存放的資料是所有資料,但是勝在屬性列少,只有提供索引的幾個屬性列,這樣的話我們只需要select * from brand_temp where … limit 400,10(插敘第41頁的資料,每頁顯示5條資料),然後我們獲取了id之後就可以去對應的表中查詢了

本作品採用《CC 協議》,轉載必須註明作者和本文連結
你還差得遠吶!

相關文章