Java猿社區—ShardingSphere之跨庫分頁帶來的性能問題與常用解決辦法

Java猿社區—ShardingSphere之跨庫分頁帶來的性能問題與常用解決辦法


參考:
ShardingSphere中文文檔

分庫分表的幾種常見玩法及如何解決跨庫查詢等問題

一次shardingjdbc踩坑引起的胡思亂想

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

假設頁大小20,如從從庫im_team_messsage0,im_team_messsage1查詢,使用者編寫的sql如下(只查詢第1000行到第1010行)

SELECT * FROM im_team_messsage ORDER BY send_at DESC LIMIT 1000, 10;

shardingsphere的改寫引擎會對此sql進行改寫,可以看到ss將limit後解析成從第一行開始查詢到第1010行

SELECT * FROM im_team_messsage0 ORDER BY send_at DESC LIMIT 0, 1010;
SELECT * FROM im_team_messsage1 ORDER BY send_at DESC LIMIT 0, 1010;

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-baIGWOGp-1584131315424)(evernotecid://6438F78B-FBEF-42D1-A152-F4935CA4BBB8/appyinxiangcom/15654258/ENResource/p11787)]

數據庫端的查詢壓力都是差不多的, 因爲都是要差不多要掃描1010行才能取得到數據. 不同的是改寫sql後, 客戶端的內存消耗和網絡消耗變大了.
shardingsphere巧妙地利用流式處理和優先級隊列結合的方式(“流式歸併”),消除了客戶端內存消耗的壓力, 但是網絡消耗的影響依然是無法消除.

如何避免使用limit帶來的效率問題呢

有很多方法可以避免使用LIMIT進行分頁。比如構建行記錄數量與行偏移量的二級索引,或使用上次分頁數據結尾ID作爲下次查詢條件的分頁方式等。

使用上次分頁數據結尾ID作爲下次查詢條件(適合在線客服)

目前這種方式作爲在線客服的消息表分頁比較合適

這種方式需要和業務溝通好,做好業務折衷,比如禁止跳頁查詢。

前提:使用shardingsphere分佈式id遞增雪花算法保證id呈現連續性:
使用上次分頁數據結尾ID作爲下次查詢條件
但同時需要注意的是,由於排序的需要,大量的數據仍然需要傳輸到ShardingSphere的內存空間。 因此,採用LIMIT這種方式分頁,並非最佳實踐。 由於LIMIT並不能通過索引查詢數據,因此如果可以保證ID的連續性,通過ID進行分頁是比較好的解決方案,例如:

SELECT * FROM im_team_message WHERE id > 100000 AND id <= 100010 ORDER BY id;

或通過記錄上次查詢結果的最後一條記錄的ID進行下一頁的查詢,例如:

SELECT * FROM im_team_message WHERE id > 10000000 LIMIT 10;

同理,使用上次分頁數據結尾的時間戳作爲下次查詢條件也可以(按照時間進行排序)。

二次查詢法

這種方法能夠滿足業務的精確需要,無需業務折衷,又高性能的方法,缺點是業務代碼複雜且需要進行兩次數據庫查詢。

請移步到:業界難題-“跨庫分頁”的四種方案

分頁子查詢(Mysql、Oracle)

Oracle和SQLServer的分頁都需要通過子查詢來處理,ShardingSphere支持分頁相關的子查詢。

  • Oracle

支持使用rownum進行分頁:

SELECT * FROM (SELECT row_.*, rownum rownum_ FROM (SELECT o.order_id as order_id FROM t_order o JOIN t_order_item i ON o.order_id = i.order_id) row_ WHERE rownum <= ?) WHERE rownum > ?

目前不支持rownum + BETWEEN的分頁方式。

  • MySQL

MySQL和PostgreSQL都支持LIMIT分頁,無需子查詢:

SELECT * FROM t_order o ORDER BY id LIMIT ? OFFSET ?
歡迎加入Java猿社區!
免費領取我歷年收集的所有學習資料哦!

歡迎加入Java猿社區.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章