亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL + ES + MongoDB 如何兼容實現上億數據的深度分頁

發布時間:2020-07-30 11:40:11 來源:億速云 閱讀:227 作者:Leah 欄目:編程語言

MySQL + ES + MongoDB 如何兼容實現上億數據的深度分頁?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

面試題 & 真實經歷

面試題:在數據量很大的情況下,怎么實現深度分頁?

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

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

慘痛的教訓

首先必須明確一點:深度分頁可以做,但是<font color="red">深度隨機跳頁絕對需要禁止。</font>

上一張圖:

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 + ES + MongoDB 如何兼容實現上億數據的深度分頁的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

都兰县| 牡丹江市| 瑞昌市| 洛扎县| 方城县| 滨海县| 儋州市| 奉贤区| 渭南市| 宝山区| 登封市| 乃东县| 天气| 康平县| 红原县| 西安市| 丹东市| 新巴尔虎右旗| 达孜县| 大关县| 昌吉市| 陇川县| 赫章县| 聂荣县| 三门峡市| 长沙市| 正蓝旗| 常熟市| 葵青区| 日土县| 淳安县| 阿克苏市| 温泉县| 高青县| 屏东县| 新津县| 邹平县| 甘孜县| 无锡市| 浦城县| 湖南省|