現身說法:實際業務出發分析百億數據量下的多表查詢優化

来源:https://www.cnblogs.com/yilezhu/archive/2019/03/14/10530223.html
-Advertisement-
Play Games

今天給大家帶來的討論主題是通過實戰經驗來對百億數據量下的多表數據查詢進行優化,俗話說的好,一切脫離業務的架構都是耍流氓,接下來我就整理一下今天早上微信群里石頭哥給大家分享的百億數據量多表查詢架構以及優化思路。由於本文內容整理自微信群,爬樓不易,整理更不易,如果有遺漏,歡迎大家在評論區留言。 作者:依 ...


今天給大家帶來的討論主題是通過實戰經驗來對百億數據量下的多表數據查詢進行優化,俗話說的好,一切脫離業務的架構都是耍流氓,接下來我就整理一下今天早上微信群里石頭哥給大家分享的百億數據量多表查詢架構以及優化思路。由於本文內容整理自微信群,爬樓不易,整理更不易,如果有遺漏,歡迎大家在評論區留言。

作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/10530223.html

簡單的例子

這裡我們先舉個簡單的例子,來個開胃菜,然後再引出今天的訪談主題。

舉例:比如我們的CzarCms系統許可權系統設計中的兩張表:用戶表以及角色表,這兩張表有關聯關係。這時候如果我要取一萬個用戶的數據,然後用戶數據又需要關聯角色表來查詢對應的角色名稱,這時候你會怎麼做呢?

按照以往我們的經驗我們會對大表進行儘可能的拆分,能分表就分表。我們在取數據的時候使用下join查詢即可實現。

可是,當我們的系統變得足夠大的時候,假設我們的用戶表有一百萬的用戶了,角色表也有近10萬的數據,這個時候我們如果還繼續使用Join進行查詢的時候就會變得非常慢了!

這時候我們可以改變下思路:就是先把一萬條用戶數據取出來,然後取所有角色id後再去重的組合,然後用一個查詢把所有的角色信息取出來,再在記憶體中進行相應的拼接處理。
這種思路勉強能夠支撐。

可是如果數據量變得越來越大,這時候我們應該如何來進行處理呢?且看下麵來自百億數據實操的經典訪談。

實際業務場景分析

第一段介紹

這裡,石頭哥就以他們公司的實際情況為例來進行了相關的實例闡述:
我們的主要表,都是幾億到幾十億行,一個join不小心就可以弄死資料庫,
而且每天1億包裹在路上,產生3億多掃描數據
數據存儲最少T+1,保存完整的一個月,也就是30到60天
數據量90到180億
這裡面,最常見的就是省,市,區,網點,人員,這5個欄位
很久以前,我們只有三五百萬業務量的時候,大家都是join五次
後來為了省事,用了10個欄位,提前把名稱寫進去
再後來,發現虧大了
多花了好多空間,並且join不一定是只需要名稱欄位
於是,進入了新時代,所有數據表都有那基本的5個欄位,不許join
查詢出來數據後,在記憶體中再關聯省,市,區,網點,人員等信息
地區5萬行,網點3萬行,人員100萬,全部提前載入到記憶體,加起來不到100M
我們小部門有100台伺服器,絕大部分用到這些基礎數據
不僅僅上百億的掃描表,其它業務表,幾乎都會帶有這些欄位,所以,緩存基礎數據,不吃虧

互動環節

  1. 多大的數據量,才不能用join?
    答:一般來說,從表100萬以內,我們都建議記憶體緩存,10萬以內必須用進程內緩存,沒得商量,記憶體中進行關聯即可。
  2. 我們刪數據只能一條條刪。不允許批刪除,這個怎麼辦?
    答:你們DBA可以辭退了,這麼簡單的事情都不會。
    大數據分析的時候,每個月幾個億數據,一條條刪,刪到何年何月啊,當然是整個分區幹掉啦
  3. 可以分享一下你們的緩存方案嗎?
    這個就不用了吧,我覺得很多大佬關於緩存的文章就寫得非常好!
    我這裡只補充一些量化的數字:記憶體速度是Redis速度100倍,Redis緩存速度是資料庫至少10倍。
    10萬以內數據量必須緩存在進程內,100萬~1億數據緩存在Redis,10萬~100萬可以上下商量,超高查詢量(比如每天10億次)時放記憶體。
    很多文章真的寫得挺好的,就是少了點經驗數據支撐,讀者搞不清楚什麼時候該用這個,什麼時候該用那個。

  4. 吉吉:以下場景:假設緩存了地區,比如查詢人員檔案信息列表是1萬行 以前是關聯查詢 現在緩存地區不能關聯查詢 只能查出一萬條然後迴圈拼接地區顯示 ,因為一萬行顯示本身這場景就不可能,所以增加翻頁 一頁顯示20行 完全不會性能問題 這樣做對嗎 求教?
    答:是的,查詢一頁20行,理論上要去匹配20次地區,但是地區數據少,省市區才四五千行,省市區加上鄉鎮街道也不過5萬行,可以全量緩存到記憶體。

吉吉:明白 謝謝 只是舉例 這種思路真的很正確 我們總是從技術考慮全部場景卻不考慮產品本身根本不能一勞永逸的搞。

  1. 真是太牛逼了!感謝分享
    答:這麼Low的辦法,大家都可以想得到,只是可能缺少一個遇到這個數據量的機會罷了,這是咱們.net的際遇,遇到問題可以見招拆招.

  2. 你說的緩存到進程內,那多個進程內數據怎麼保持一致?
    答:不保持一致,因為進程級緩存,可以定時更新的,我們方案是預設10秒非同步更新緩存,然後也可以按照添刪改隨時更新。

  3. 我的記憶體數據以哪個為準?如果我機器是負載均衡,那麼幾個副本記憶體不一樣啊!
    答:以本機為準,沒關係,每台伺服器上都有一份緩存。緩存10萬用戶信息,一共也就10M左右記憶體,你還在意?
  4. 數據怎麼進行存儲呢?
    答:記憶體字典進行存儲,最常用的就是並行字典 ConcurrentDictionary。

  5. 假設你說的人員數據,那就必然存在 某一時刻 A進程10000人,B進程10002人,可能十秒可能八秒,但你們體量這麼大,這個問題不需要處理嗎
    答:沒錯,的確存在這樣的問題,我們公司有100萬人員,但是全公司都知道,新加一個帳號,往往要兩三天才能在100多個內部系統全部生效,甚至新簽約一家網點,也要兩三天以後,各個系統才會認它,等你有那個體量的時候,就可以接受更長的不一致時間,我們在淘寶開店,發佈商品,有時候發佈成功了,跳轉到詳情頁卻是看不到的,等幾秒就好了。
    另外,
    我再說一句噁心一點的情況,大家別拍磚啊,在百億級數據量之下,就算我算錯個幾百幾千,那又怎麼樣???又怎麼樣??
    對內,我會嚴格要求部門人員,務必追求準確;
    對外,我會反覆提醒部門人員,我們提供的數據精度,最高99.99%,你要敢浪費大量時間在0.01%上,我就敢給你績效C
    不用太死板嘛,把整體工作搞定,讓系統穩定工作,那才是咱們的主要工作
    用戶有萬分之一的機會看到不正確的數據,只要再刷新一次能夠正確,就一定不是bug
    萬分之一看到不正確的數據,並且只是萬分之一的偏差而已
    由此換取的好處是,我們再也不用擔心各種該死的“數據一致性。

總結

今天非常感謝石頭哥的精彩分享,相信只有實際的業務操作經驗才會有如此深刻的講解!一切從實際業務出發,脫離理論,實踐出真知。還是印證了那句話,一切脫離實際業務的架構都是耍流氓!感謝大家的閱讀。

有想進一步瞭解石頭哥的可以這篇文章《論一個程式員的自我修養-從一張圖片說起

最後為石頭哥的XCode打個廣告:

NewLife.XCode是一個有10多年曆史的開源數據中間件,支持nfx/netstandard,由新生命團隊(2002~2019)開發完成並維護至今,以下簡稱XCode。
xcode在2018年已經完成對大數據場景的特殊優化改造,2019年的目標是是針對分散式數據場景的優化。
最近石頭哥也在為XCode編寫系列教程:
整個系列教程會大量結合示例代碼和運行日誌來進行深入分析,蘊含多年開發經驗於其中,代表作有百億級大數據實時計算項目。

開源地址:https://github.com/NewLifeX/X(求star, 670+)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、 jQuery和CSS3支持移動手機的DOM元素移動和縮放插件:panzoom 2、拖動:jqueryUI-Draggable、touchpunch 3、圖表:echart、heightChart、d3 <template> <div class="topdivall"> <div class= ...
  • public class info() { public string name{get;set;} public string age{get;set;} } list<info> list = new list<info>(); list.ForEach(i=> { if(i.name=="xx ...
  • ifrem上傳文件後顯示 1、上傳文件按鈕 <a class="btn btn-primary pull-right" id="data-upload" style="margin-right:10px;" data-target="#UploadFiles" data-toggle="modal" ...
  • // string data = "{\"uid\":515,\"timestamp\":\"2018 - 5 - 25 19:05:00\",\"encode\":\"3A19E9D6EAFF2FA9160ED6981EB522E1\"}"; /// <summary> /// 與適當性認證相關的 ...
  • --一本錯誤的記錄 insert into Book values('錯誤時怎樣練成的',111) --左連接 select s.name,b.name from student as s left join Book as b on s.id=b.studentid --右連接 select s. ...
  • 一般而言webservice是部署在哪台伺服器,然後它的address location就是指向哪個,但是由於有些情況處於各種原因,如網路策略,需要先訪問某個ip之後再進行跳轉到一個ip,這個時候就需要代碼控制websevice指向的IP地址了,就需要用到SoapExtensionReflector ...
  • 裝箱:值類型-->引用類型。 拆箱:引用類型-->值類型 裝箱:把值類型拷貝一份到堆里。反之拆箱。 具有父子關係 是拆裝箱的條件之一。 所以: 裝的什麼類型,拆的時候也必須是對應類型。 使用方法時看是否裝拆箱:看需要的參數和傳入的參數的集體類型。 使用泛型集合避免裝拆箱。 ...
  • MVC頁面擴展方法 單例模式 /// <summary> /// 創建一個Config內容對象 /// </summary> /// <param name=""></param> /// <param name="key"></param> /// <returns></returns> publ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...