首頁 後端開發 php教程 如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

Jul 27, 2020 pm 05:24 PM
mysql

如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

「訪談問題& 真實經驗

面試題:在資料量很大的情況下,怎麼實現深度分頁? 大家在面試時,或是準備面試中可能會遇到上述的問題,大多的回答基本上是分庫分錶建索引,這是一種很標準的正確回答,但現實總是很骨感,所以面試官通常會追問你一句,現在工期不足,人員不足,該怎麼實現深度分頁?

這時候沒有實​​際經驗的同學基本麻爪,So,請聽我娓娓道來。

慘痛的教訓如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

首先必須明確一點:深度分頁可以做,但深度隨機跳頁絕對需要禁止。

上一張圖:

你猜,我點第142360頁,服務會不會爆炸?

像MySQL,MongoDB資料庫還好,本身就是專業的資料庫,處理的不好,最多就是慢,但如果涉及到ES,性質就不一樣了,我們只好利用SearchAfter Api,去循環取得數據,這就牽扯到記憶體佔用的問題,如果當時程式碼寫的不優雅,直接就可能導致記憶體溢出。

為什麼不能允許隨機深度跳頁

從技術的角度淺顯的聊一聊為什麼不能允許隨機深度跳頁,或者說為什麼不建議深度分頁

MySQL

分頁的基本原理:

SELECT * FROM test ORDER BY id DESC LIMIT 10000, 20;
登入後複製

LIMIT 10000 , 20的意思掃描滿足條件的10020行,丟掉前面的10000行,返回最後的20行。如果是LIMIT 1000000 , 100,需要掃描1000100 行,在一個高並發的應用程式裡,每次查詢需要掃描超過100W行,不炸才怪。

MongoDB

分頁的基本原理:

db.t_data.find().limit(5).skip(5);
登入後複製

同樣的,隨著頁碼的增大,skip 跳過的項目也會隨之變大,而這個操作是透過cursor 的迭代器來實現的,對於cpu的消耗會非常明顯,當頁碼非常大時且頻繁時,必然爆炸。

  • ElasticSearch

  • 從業務的角度來說,ElasticSearch不是典型的資料庫,它是搜尋引擎,如果在篩選條件下沒有搜尋想要的數據,繼續深度分頁也不會找到想要的數據,退一步講,假如我們把ES作為數據庫來使用進行查詢,在進行分頁的時候一定會遇到max_result_window 的限制,看到沒,官方都告訴你最大偏移量限制是一萬。
  • 查詢流程:

  • 如查詢第501頁,每頁10條,客戶端傳送請求到某節點

  • 此節點將數據廣播到各個分片,各分片各自查詢前5010 條數據

#查詢結果返回至該節點,然後對數據進行整合,取出前5010 條數據

回傳給客戶端

由此可以看出為什麼要限制偏移量,另外,如果使用Search After 這種捲動式API進行深度跳頁查詢,也是一樣需要每次滾動幾千條,可能一共需要滾動上百萬,千萬條數據,就為了最後的20條數據,效率可想而知。

再一次和產品對線

俗話說的好,技術解決不了的問題,就由業務來解決!

在實習的時候信了產品的邪,必須實現深度分頁跳頁,如今必須撥亂反正,業務上必須有如下更改:如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

盡可能的增加默認的篩選條件,如:時間週期,目的是為了減少資料量的展示

修改跳頁的展現方式,改為滾動顯示,或小範圍跳頁

如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?滾動顯示參考圖:

小規模跳頁參考圖:

  • 通用解決方案

  • #短時間內快速解決的方案主要是以下幾點:

  • 必備:對排序字段,篩選條件務必設定好索引

#核心:利用小範圍頁碼的已知數據,或捲動載入的已知數據,減少偏移量

額外:如果遇到不好處理的情況,也可以取得多餘的數據,進行一定的截取,效能影響並不大

#######MySQL#########原分頁SQL:###
# 第一页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit 0, 20;
# 第N页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit (N - 1) * 20, 20;
登入後複製
###透過上下文關係,改寫為:###
# XXXX 代表已知的数据
SELECT * FROM `year_score` where `year` = 2017 and id > XXXX ORDER BY id limit 20;
登入後複製

在 没内鬼,来点干货!SQL优化和诊断 一文中提到过,LIMIT会在满足条件下停止查询,因此该方案的扫描总量会急剧减少,效率提升Max!

ES

方案和MySQL相同,此时我们就可以随用所欲的使用 FROM-TO Api,而且不用考虑最大限制的问题。

MongoDB

方案基本类似,基本代码如下:

如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

相关性能测试:

如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?

如果非要深度随机跳页

如果你没有杠过产品经理,又该怎么办呢,没关系,还有一丝丝的机会。

在 SQL优化 一文中还提到过MySQL深度分页的处理技巧,代码如下:

# 反例(耗时129.570s)
select * from task_result LIMIT 20000000, 10;
# 正例(耗时5.114s)
SELECT a.* FROM task_result a, (select id from task_result LIMIT 20000000, 10) b where a.id = b.id;
# 说明
# task_result表为生产环境的一个表,总数据量为3400万,id为主键,偏移量达到2000万
登入後複製

该方案的核心逻辑即基于聚簇索引,在不通过回表的情况下,快速拿到指定偏移量数据的主键ID,然后利用聚簇索引进行回表查询,此时总量仅为10条,效率很高。

因此我们在处理MySQL,ES,MongoDB时,也可以采用一样的办法:

  • 限制获取的字段,只通过筛选条件,深度分页获取主键ID

  • 通过主键ID定向查询需要的数据

瑕疵:当偏移量非常大时,耗时较长,如文中的 5s

推荐教程:《MySQL教程

文章来源:https://juejin.im/post/5f0de4d06fb9a07e8a19a641

以上是如何相容於 MySQL + ES + MongoDB 實現上億資料的深度分頁?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

MySQL:初學者的數據管理易用性 MySQL:初學者的數據管理易用性 Apr 09, 2025 am 12:07 AM

MySQL適合初學者使用,因為它安裝簡單、功能強大且易於管理數據。 1.安裝和配置簡單,適用於多種操作系統。 2.支持基本操作如創建數據庫和表、插入、查詢、更新和刪除數據。 3.提供高級功能如JOIN操作和子查詢。 4.可以通過索引、查詢優化和分錶分區來提升性能。 5.支持備份、恢復和安全措施,確保數據的安全和一致性。

phpmyadmin怎麼打開 phpmyadmin怎麼打開 Apr 10, 2025 pm 10:51 PM

可以通過以下步驟打開 phpMyAdmin:1. 登錄網站控制面板;2. 找到並點擊 phpMyAdmin 圖標;3. 輸入 MySQL 憑據;4. 點擊 "登錄"。

mysql:簡單的概念,用於輕鬆學習 mysql:簡單的概念,用於輕鬆學習 Apr 10, 2025 am 09:29 AM

MySQL是一個開源的關係型數據庫管理系統。 1)創建數據庫和表:使用CREATEDATABASE和CREATETABLE命令。 2)基本操作:INSERT、UPDATE、DELETE和SELECT。 3)高級操作:JOIN、子查詢和事務處理。 4)調試技巧:檢查語法、數據類型和權限。 5)優化建議:使用索引、避免SELECT*和使用事務。

MySQL和SQL:開發人員的基本技能 MySQL和SQL:開發人員的基本技能 Apr 10, 2025 am 09:30 AM

MySQL和SQL是開發者必備技能。 1.MySQL是開源的關係型數據庫管理系統,SQL是用於管理和操作數據庫的標準語言。 2.MySQL通過高效的數據存儲和檢索功能支持多種存儲引擎,SQL通過簡單語句完成複雜數據操作。 3.使用示例包括基本查詢和高級查詢,如按條件過濾和排序。 4.常見錯誤包括語法錯誤和性能問題,可通過檢查SQL語句和使用EXPLAIN命令優化。 5.性能優化技巧包括使用索引、避免全表掃描、優化JOIN操作和提升代碼可讀性。

navicat premium怎麼創建 navicat premium怎麼創建 Apr 09, 2025 am 07:09 AM

使用 Navicat Premium 創建數據庫:連接到數據庫服務器並輸入連接參數。右鍵單擊服務器並選擇“創建數據庫”。輸入新數據庫的名稱和指定字符集和排序規則。連接到新數據庫並在“對象瀏覽器”中創建表。右鍵單擊表並選擇“插入數據”來插入數據。

navicat怎麼新建連接mysql navicat怎麼新建連接mysql Apr 09, 2025 am 07:21 AM

可在 Navicat 中通過以下步驟新建 MySQL 連接:打開應用程序並選擇“新建連接”(Ctrl N)。選擇“MySQL”作為連接類型。輸入主機名/IP 地址、端口、用戶名和密碼。 (可選)配置高級選項。保存連接並輸入連接名稱。

navicat如何執行sql navicat如何執行sql Apr 08, 2025 pm 11:42 PM

在 Navicat 中執行 SQL 的步驟:連接到數據庫。創建 SQL 編輯器窗口。編寫 SQL 查詢或腳本。單擊“運行”按鈕執行查詢或腳本。查看結果(如果執行查詢的話)。

Navicat 連接數據庫錯誤代碼及解決辦法 Navicat 連接數據庫錯誤代碼及解決辦法 Apr 08, 2025 pm 11:06 PM

Navicat 連接數據庫時常見的錯誤及解決方案:用戶名或密碼錯誤(Error 1045)防火牆阻止連接(Error 2003)連接超時(Error 10060)無法使用套接字連接(Error 1042)SSL 連接錯誤(Error 10055)連接嘗試過多導致主機被阻止(Error 1129)數據庫不存在(Error 1049)沒有權限連接到數據庫(Error 1000)

See all articles