MySQL 亿级数据需求的优化思路(二),100亿数据,1万字段属性的秒级检索
最近在研究?jī)|級(jí)數(shù)據(jù)的時(shí)候,無(wú)意中看到了一個(gè)關(guān)于寫(xiě)58同城的文章
https://blog.csdn.net/admin1973/article/details/55251499?from=timeline
其實(shí)上面講的version+ext的方式以及壓縮json的思路,對(duì)于我來(lái)講都可以看得懂,想得通,其實(shí)最感興趣的還是他們那個(gè)E-Search架構(gòu),然后開(kāi)始進(jìn)行實(shí)驗(yàn)和研究其算法。
上圖是從那篇文章里扒出來(lái)的圖,是由他們58幾個(gè)牛人寫(xiě)的,并維護(hù)的。
按照我的理解一步一步的進(jìn)行邏輯剖析,有誤的話希望大嬸們及時(shí)評(píng)論改正。?
分析思路開(kāi)始:
| tid | uid | time | cateid | ext |
| 1 | 1 | 123 | 招聘 | {"job":"driver","salary":8000,"location":"bj"} |
| 2 | 1 | 345 | 房產(chǎn) | {"rent":1000,"location":"dl","acreage":120} |
| 3 | 1 | 567 | 二手 | {"type":"iphone","money",200} |
這個(gè)是文章里提到的數(shù)據(jù)表結(jié)構(gòu),ext存這比較多可擴(kuò)展的屬性。然后E-Search就是要對(duì)這些屬性進(jìn)行快速的查詢搜索。
里面提到了Searcher1?Searcher2,就是一個(gè)個(gè)用于建立索引用的表。
比如房產(chǎn):
?
房產(chǎn)現(xiàn)在里面有三個(gè)字段,每一個(gè)字段對(duì)應(yīng)一張表或多張表,因?yàn)樽侄螖?shù)據(jù)到一定數(shù)量的時(shí)候,可能單臺(tái)服務(wù)器的存儲(chǔ)空間不夠了,所以需要分庫(kù)分表。分表可以按照Hash算法,然后切割成單臺(tái)服務(wù)器可以容下的數(shù)量范圍,在超過(guò)一定冗余范圍,就要增加一臺(tái)冗余服務(wù)器,繼續(xù)分庫(kù)分表。上面的例子,按照每張表存儲(chǔ)100萬(wàn)數(shù)據(jù)的方式存儲(chǔ)。
里面提到merger服務(wù),合并層,并且強(qiáng)調(diào)了,增加機(jī)器就可以擴(kuò)容,同時(shí)也說(shuō)明了服務(wù)啟動(dòng)時(shí)可以加載索引數(shù)據(jù)到內(nèi)存,請(qǐng)求訪問(wèn)時(shí)從內(nèi)存中l(wèi)oad數(shù)據(jù),訪問(wèn)速度很快。
那這個(gè)merger要做些什么呢?應(yīng)該怎么做呢?
好了,現(xiàn)在分析業(yè)務(wù)需求,咱們模擬一個(gè)場(chǎng)景和一個(gè)查詢需求,分析一下整體是怎么工作的。
在看了58同城網(wǎng)站時(shí)候,發(fā)現(xiàn)了幾個(gè)特點(diǎn)。
一、有分頁(yè),但是沒(méi)有一共多少條的分析和統(tǒng)計(jì)
二、檢索條件是可以隨意的設(shè)定,有很多的條件可以進(jìn)行添加
然后我們沿著我們的表設(shè)計(jì)開(kāi)始進(jìn)行模擬一個(gè)搜索過(guò)程。
那么,我們假設(shè)幾個(gè)查詢條件
價(jià)格:1700~2500
地址:大連 (dl)
面積:190平米以內(nèi)
按照價(jià)格從低到高進(jìn)行排序
分頁(yè)每頁(yè)10條
按照以上的查詢條件,我們分別在這六張表上進(jìn)行搜索。
租金:Table1 2000條,Table2 500條,一共2500條
地址:Table3?999993條,Table4 8條,一共 1000001條
面積:Table5 5000條
下一步,當(dāng)然就要把這些條件查詢的結(jié)果進(jìn)行合并,就是所謂的merger要做的事。
首先,要知道排序要用價(jià)格從低到高進(jìn)行排序,我們知道查詢結(jié)果就是按照索引進(jìn)行排序好的排序文件,大小就是12345這樣從低到高進(jìn)行索引的。那就從Table1開(kāi)始循環(huán),因?yàn)槭莂nd關(guān)系,只要數(shù)據(jù)既符合地址的條件,又符合面積的條件,就算合格一條,只要累積滿足了10條,就可以返回了。這個(gè)時(shí)候,其他的條件加載在內(nèi)存里,但怎么比較比較快呢?
這時(shí)候,就涉及到Hash算法了,比如Java有個(gè)HashMap,我們可以把其他數(shù)據(jù)全部加載到HashMap里,然后Table1每循環(huán)一次要用containsKey方法,與其他的表進(jìn)行確認(rèn)一下是否存在,由于Hash算法速度很快,就可以很快的湊出來(lái)前10條。
這個(gè)時(shí)候,第一頁(yè)的結(jié)果就完成了。
那么,就要問(wèn)了,第二頁(yè),第三頁(yè),第四頁(yè)怎么辦?
在我們循環(huán)Table1的時(shí)候,會(huì)有一個(gè)循環(huán)的游標(biāo)位置,index,比如湊了10條,游標(biāo)游到了25才湊齊返回,那我們就把這個(gè)25一同返回,作為下一頁(yè)的起點(diǎn)。
由于系統(tǒng)不需要統(tǒng)計(jì)一共查詢多少結(jié)果,所以我們依次往下迭代就可以了。
前臺(tái)得到了25這個(gè)游標(biāo),那么,下一頁(yè)直接從Table1結(jié)果25在往后開(kāi)始循環(huán)尋找條件符合的數(shù)據(jù),湊成10條,并且返回index ,依次往后進(jìn)行。
?
其他問(wèn)題總結(jié):
一、索引表冗余問(wèn)題
就像那個(gè)文章所說(shuō)的,系統(tǒng)不要求一致性,所以每次有新的數(shù)據(jù)插入,在插入Ext表之后,分別給到searcher的索引表里,進(jìn)行更新索引,當(dāng)某個(gè)字段索引表空間不夠了,增加冗余服務(wù)器,進(jìn)行切分?jǐn)?shù)據(jù)以保證重建索引速度及存放空間能力。
二、merger服務(wù)冗余問(wèn)題
由于merger服務(wù)與索引表在同一服務(wù)器上,當(dāng)表控件需要增加的時(shí)候,merger服務(wù)也隨著增加,同時(shí)要保證這臺(tái)服務(wù)器的內(nèi)存能夠可以實(shí)現(xiàn)單表最大數(shù)據(jù)存儲(chǔ)計(jì)算能力。
三、EXT數(shù)據(jù)的冗余問(wèn)題
直接就按照UID的增加,如果單臺(tái)服務(wù)器不夠,直接增加
四、100億數(shù)據(jù)導(dǎo)入問(wèn)題
有個(gè)100億的數(shù)據(jù)問(wèn)題,要求從Oracle數(shù)據(jù)庫(kù)導(dǎo)入到MySql下。要求原系統(tǒng)不能停,還要求最后的數(shù)據(jù)是一致的。這個(gè)思路就是,把MySql進(jìn)行分庫(kù)分表規(guī)劃好后,進(jìn)行導(dǎo)數(shù)據(jù),并且業(yè)務(wù)系統(tǒng)在不停的情況下產(chǎn)生的新的操作,同時(shí)更新Oracle和MySql,最后就可以實(shí)現(xiàn)兩個(gè)庫(kù)的一致性。?
總結(jié)
以上是生活随笔為你收集整理的MySQL 亿级数据需求的优化思路(二),100亿数据,1万字段属性的秒级检索的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Mysql插入很慢,找到了稍微快点的方法
- 下一篇: sql2008“备份集中的数据库备份与现