现身说法:实际业务出发分析百亿数据量下的多表查询优化
今天給大家?guī)?lái)的討論主題是通過(guò)實(shí)戰(zhàn)經(jīng)驗(yàn)來(lái)對(duì)百億數(shù)據(jù)量下的多表數(shù)據(jù)查詢進(jìn)行優(yōu)化,俗話說(shuō)的好,一切脫離業(yè)務(wù)的架構(gòu)都是耍流氓,接下來(lái)我就整理一下今天早上微信群里石頭哥給大家分享的百億數(shù)據(jù)量多表查詢架構(gòu)以及優(yōu)化思路。由于本文內(nèi)容整理自微信群,爬樓不易,整理更不易,如果有遺漏,歡迎大家在評(píng)論區(qū)留言。
簡(jiǎn)單引子一個(gè)例子引出主題舉例:比如我們的CzarCms系統(tǒng)權(quán)限系統(tǒng)設(shè)計(jì)中的兩張表:用戶表以及角色表,這兩張表有關(guān)聯(lián)關(guān)系。這時(shí)候如果我要取一萬(wàn)個(gè)用戶的數(shù)據(jù),然后用戶數(shù)據(jù)又需要關(guān)聯(lián)角色表來(lái)查詢對(duì)應(yīng)的角色名稱,這時(shí)候你會(huì)怎么做呢?
按照以往我們的經(jīng)驗(yàn)我們會(huì)對(duì)大表進(jìn)行盡可能的拆分,能分表就分表。我們?cè)谌?shù)據(jù)的時(shí)候使用下join查詢即可實(shí)現(xiàn)。
可是,當(dāng)我們的系統(tǒng)變得足夠大的時(shí)候,假設(shè)我們的用戶表有一百萬(wàn)的用戶了,角色表也有近10萬(wàn)的數(shù)據(jù),這個(gè)時(shí)候我們?nèi)绻€繼續(xù)使用Join進(jìn)行查詢的時(shí)候就會(huì)變得非常慢了!
這時(shí)候我們可以改變下思路:就是先把一萬(wàn)條用戶數(shù)據(jù)取出來(lái),然后取所有角色id后再去重的組合,然后用一個(gè)查詢把所有的角色信息取出來(lái),再在內(nèi)存中進(jìn)行相應(yīng)的拼接處理。這種思路勉強(qiáng)能夠支撐。
可是如果數(shù)據(jù)量變得越來(lái)越大,這時(shí)候我們應(yīng)該如何來(lái)進(jìn)行處理呢?且看下面來(lái)自百億數(shù)據(jù)實(shí)操的經(jīng)典訪談。
場(chǎng)景介紹
這里,石頭哥就以他們公司的實(shí)際情況為例來(lái)進(jìn)行了相關(guān)的實(shí)例闡述:
我們的主要表,都是幾億到幾十億行,一個(gè)join不小心就可以弄死數(shù)據(jù)庫(kù),
而且每天1億包裹在路上,產(chǎn)生3億多掃描數(shù)據(jù)
數(shù)據(jù)存儲(chǔ)最少T+1,保存完整的一個(gè)月,也就是30到60天
數(shù)據(jù)量90到180億
這里面,最常見的就是省,市,區(qū),網(wǎng)點(diǎn),人員,這5個(gè)字段
很久以前,我們只有三五百萬(wàn)業(yè)務(wù)量的時(shí)候,大家都是join五次
后來(lái)為了省事,用了10個(gè)字段,提前把名稱寫進(jìn)去
再后來(lái),發(fā)現(xiàn)虧大了
多花了好多空間,并且join不一定是只需要名稱字段
于是,進(jìn)入了新時(shí)代,所有數(shù)據(jù)表都有那基本的5個(gè)字段,不許join
查詢出來(lái)數(shù)據(jù)后,在內(nèi)存中再關(guān)聯(lián)省,市,區(qū),網(wǎng)點(diǎn),人員等信息
地區(qū)5萬(wàn)行,網(wǎng)點(diǎn)3萬(wàn)行,人員100萬(wàn),全部提前加載到內(nèi)存,加起來(lái)不到100M
我們小部門有100臺(tái)服務(wù)器,絕大部分用到這些基礎(chǔ)數(shù)據(jù)
不僅僅上百億的掃描表,其它業(yè)務(wù)表,幾乎都會(huì)帶有這些字段,所以,緩存基礎(chǔ)數(shù)據(jù),不吃虧
互動(dòng)環(huán)節(jié)
1. 多大的數(shù)據(jù)量,才不能用join?
答:一般來(lái)說(shuō),從表100萬(wàn)以內(nèi),我們都建議內(nèi)存緩存,10萬(wàn)以內(nèi)必須用進(jìn)程內(nèi)緩存,沒(méi)得商量,內(nèi)存中進(jìn)行關(guān)聯(lián)即可。
2. 我們刪數(shù)據(jù)只能一條條刪。不允許批刪除,這個(gè)怎么辦?
答:你們DBA可以辭退了,這么簡(jiǎn)單的事情都不會(huì)。
大數(shù)據(jù)分析的時(shí)候,每個(gè)月幾個(gè)億數(shù)據(jù),一條條刪,刪到何年何月啊,當(dāng)然是整個(gè)分區(qū)干掉啦
3. 可以分享一下你們的緩存方案嗎?
這個(gè)就不用了吧,我覺(jué)得很多大佬關(guān)于緩存的文章就寫得非常好!
我這里只補(bǔ)充一些量化的數(shù)字:內(nèi)存速度是Redis速度100倍,Redis緩存速度是數(shù)據(jù)庫(kù)至少10倍。
10萬(wàn)以內(nèi)數(shù)據(jù)量必須緩存在進(jìn)程內(nèi),100萬(wàn)~1億數(shù)據(jù)緩存在Redis,10萬(wàn)~100萬(wàn)可以上下商量,超高查詢量(比如每天10億次)時(shí)放內(nèi)存。
很多文章真的寫得挺好的,就是少了點(diǎn)經(jīng)驗(yàn)數(shù)據(jù)支撐,讀者搞不清楚什么時(shí)候該用這個(gè),什么時(shí)候該用那個(gè)。
4. 吉吉:以下場(chǎng)景:假設(shè)緩存了地區(qū),比如查詢?nèi)藛T檔案信息列表是1萬(wàn)行? 以前是關(guān)聯(lián)查詢? 現(xiàn)在緩存地區(qū)不能關(guān)聯(lián)查詢? 只能查出一萬(wàn)條然后循環(huán)拼接地區(qū)顯示? ,因?yàn)橐蝗f(wàn)行顯示本身這場(chǎng)景就不可能,所以增加翻頁(yè) 一頁(yè)顯示20行? 完全不會(huì)性能問(wèn)題? 這樣做對(duì)嗎 求教?
答:是的,查詢一頁(yè)20行,理論上要去匹配20次地區(qū),但是地區(qū)數(shù)據(jù)少,省市區(qū)才四五千行,省市區(qū)加上鄉(xiāng)鎮(zhèn)街道也不過(guò)5萬(wàn)行,可以全量緩存到內(nèi)存。
吉吉:明白? 謝謝? 只是舉例? 這種思路真的很正確? ?我們總是從技術(shù)考慮全部場(chǎng)景卻不考慮產(chǎn)品本身根本不能一勞永逸的搞。
5. 真是太牛逼了!感謝分享
答:這么Low的辦法,大家都可以想得到,只是可能缺少一個(gè)遇到這個(gè)數(shù)據(jù)量的機(jī)會(huì)罷了,這是咱們.net的際遇,遇到問(wèn)題可以見招拆招.
6. 你說(shuō)的緩存到進(jìn)程內(nèi),那多個(gè)進(jìn)程內(nèi)數(shù)據(jù)怎么保持一致?
答:不保持一致,因?yàn)檫M(jìn)程級(jí)緩存,可以定時(shí)更新的,我們方案是默認(rèn)10秒異步更新緩存,然后也可以按照添刪改隨時(shí)更新。
7. 我的內(nèi)存數(shù)據(jù)以哪個(gè)為準(zhǔn)?如果我機(jī)器是負(fù)載均衡,那么幾個(gè)副本內(nèi)存不一樣啊!
答:以本機(jī)為準(zhǔn),沒(méi)關(guān)系,每臺(tái)服務(wù)器上都有一份緩存。緩存10萬(wàn)用戶信息,一共也就10M左右內(nèi)存,你還在意?
8. 數(shù)據(jù)怎么進(jìn)行存儲(chǔ)呢?
答:內(nèi)存字典進(jìn)行存儲(chǔ),最常用的就是并行字典 ConcurrentDictionary。
9. 假設(shè)你說(shuō)的人員數(shù)據(jù),那就必然存在 某一時(shí)刻 A進(jìn)程10000人,B進(jìn)程10002人,可能十秒可能八秒,但你們體量這么大,這個(gè)問(wèn)題不需要處理嗎
答:沒(méi)錯(cuò),的確存在這樣的問(wèn)題,我們公司有100萬(wàn)人員,但是全公司都知道,新加一個(gè)帳號(hào),往往要兩三天才能在100多個(gè)內(nèi)部系統(tǒng)全部生效,甚至新簽約一家網(wǎng)點(diǎn),也要兩三天以后,各個(gè)系統(tǒng)才會(huì)認(rèn)它,等你有那個(gè)體量的時(shí)候,就可以接受更長(zhǎng)的不一致時(shí)間,我們?cè)谔詫氶_店,發(fā)布商品,有時(shí)候發(fā)布成功了,跳轉(zhuǎn)到詳情頁(yè)卻是看不到的,等幾秒就好了。
另外,
我再說(shuō)一句惡心一點(diǎn)的情況,大家別拍磚啊,在百億級(jí)數(shù)據(jù)量之下,就算我算錯(cuò)個(gè)幾百幾千,那又怎么樣???又怎么樣??
對(duì)內(nèi),我會(huì)嚴(yán)格要求部門人員,務(wù)必追求準(zhǔn)確;
對(duì)外,我會(huì)反復(fù)提醒部門人員,我們提供的數(shù)據(jù)精度,最高99.99%,你要敢浪費(fèi)大量時(shí)間在0.01%上,我就敢給你績(jī)效C
不用太死板嘛,把整體工作搞定,讓系統(tǒng)穩(wěn)定工作,那才是咱們的主要工作
用戶有萬(wàn)分之一的機(jī)會(huì)看到不正確的數(shù)據(jù),只要再刷新一次能夠正確,就一定不是bug
萬(wàn)分之一看到不正確的數(shù)據(jù),并且只是萬(wàn)分之一的偏差而已
由此換取的好處是,我們?cè)僖膊挥脫?dān)心各種該死的“數(shù)據(jù)一致性。
1
總結(jié)END
今天非常感謝石頭哥的精彩分享,相信只有實(shí)際的業(yè)務(wù)操作經(jīng)驗(yàn)才會(huì)有如此深刻的講解!一切從實(shí)際業(yè)務(wù)出發(fā),脫離理論,實(shí)踐出真知。還是印證了那句話,一切脫離實(shí)際業(yè)務(wù)的架構(gòu)都是耍流氓!感謝大家的閱讀。
有想進(jìn)一步了解石頭哥的可以這篇文章《[論一個(gè)程序員的自我修養(yǎng)-從一張圖片說(shuō)起](https://www.cnblogs.com/yilezhu/p/10249547.html)》?
最后為石頭哥的XCode打個(gè)廣告:
NewLife.XCode是一個(gè)有10多年歷史的開源數(shù)據(jù)中間件,支持nfx/netstandard,由新生命團(tuán)隊(duì)(2002~2019)開發(fā)完成并維護(hù)至今,以下簡(jiǎn)稱XCode。
xcode在2018年已經(jīng)完成對(duì)大數(shù)據(jù)場(chǎng)景的特殊優(yōu)化改造,2019年的目標(biāo)是是針對(duì)分布式數(shù)據(jù)場(chǎng)景的優(yōu)化。
最近石頭哥也在為XCode編寫系列教程:
整個(gè)系列教程會(huì)大量結(jié)合示例代碼和運(yùn)行日志來(lái)進(jìn)行深入分析,蘊(yùn)含多年開發(fā)經(jīng)驗(yàn)于其中,代表作有百億級(jí)大數(shù)據(jù)實(shí)時(shí)計(jì)算項(xiàng)目。
開源地址:[https://github.com/NewLifeX/X ](https://github.com/NewLifeX/X)(求star, 670+)
總結(jié)
以上是生活随笔為你收集整理的现身说法:实际业务出发分析百亿数据量下的多表查询优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为什么我的会话状态在ASP.NET Co
- 下一篇: SignalR第一节-在5分钟内完成通信