1. 程式人生 > >php 大資料量及海量資料處理演算法總結

php 大資料量及海量資料處理演算法總結

下面的方法是我對海量資料的處理方法進行了一個一般性的總結,當然這些方法可能並不能完全覆蓋所有的問題,但是這樣的一些方法也基本可以處理絕大多數遇到的問題。下面的一些問題基本直接來源於公司的面試筆試題目,方法不一定最優,如果你有更好的處理方法,歡迎與我討論。 

1.Bloom filter 

適用範圍:可以用來實現資料字典,進行資料的判重,或者集合求交集 

基本原理及要點: 
對於原理來說很簡單,位陣列+k個獨立hash函式。將hash函式對應的值的位陣列置1,查詢時如果發現所有hash函式對應位都是1說明存在,很明顯這個過程並不保證查詢的結果是100%正確的。同時也不支援刪除一個已經插入的關鍵字,因為該關鍵字對應的位會牽動到其他的關鍵字。所以一個簡單的改進就是 counting Bloom filter,用一個counter陣列代替位陣列,就可以支援刪除了。 


還有一個比較重要的問題,如何根據輸入元素個數n,確定位陣列m的大小及hash函式個數。當hash函式個數k=(ln2)*(m/n)時錯誤率最小。在錯誤率不大於E的情況下,m至少要等於n*lg(1/E)才能表示任意n個元素的集合。但m還應該更大些,因為還要保證bit數組裡至少一半為 0,則m 應該>=nlg(1/E)*lge 大概就是nlg(1/E)1.44倍(lg表示以2為底的對數)。 

舉個例子我們假設錯誤率為0.01,則此時m應大概是n的13倍。這樣k大概是8個。 

注意這裡m與n的單位不同,m是bit為單位,而n則是以元素個數為單位(準確的說是不同元素的個數)。通常單個元素的長度都是有很多bit的。所以使用bloom filter記憶體上通常都是節省的。 


擴充套件: 
Bloom filter將集合中的元素對映到位陣列中,用k(k為雜湊函式個數)個對映位是否全1表示元素在不在這個集合中。Counting bloom filter(CBF)將位陣列中的每一位擴充套件為一個counter,從而支援了元素的刪除操作。Spectral Bloom Filter(SBF)將其與集合元素的出現次數關聯。SBF採用counter中的最小值來近似表示元素的出現頻率。 

問題例項:給你A,B兩個檔案,各存放50億條URL,每條URL佔用64位元組,記憶體限制是4G,讓你找出A,B檔案共同的URL。如果是三個乃至n個檔案呢? 

根據這個問題我們來計算下記憶體的佔用,4G=2^32大概是40億*8大概是340億,n=50億,如果按出錯率0.01算需要的大概是650億個 bit。現在可用的是340億,相差並不多,這樣可能會使出錯率上升些。另外如果這些urlip是一一對應的,就可以轉換成ip,則大大簡單了。 


2.Hashing 

適用範圍:快速查詢,刪除的基本資料結構,通常需要總資料量可以放入記憶體 

基本原理及要點: 
hash函式選擇,針對字串,整數,排列,具體相應的hash方法。 
碰撞處理,一種是open hashing,也稱為拉鍊法;另一種就是closed hashing,也稱開地址法,opened addressing。 (http://www.my400800.cn) 

擴充套件: 
d-left hashing中的d是多個的意思,我們先簡化這個問題,看一看2-left hashing。2-left hashing指的是將一個雜湊表分成長度相等的兩半,分別叫做T1和T2,給T1和T2分別配備一個雜湊函式,h1和h2。在儲存一個新的key時,同時用兩個雜湊函式進行計算,得出兩個地址h1[key]和h2[key]。這時需要檢查T1中的h1[key]位置和T2中的h2[key]位置,哪一個位置已經儲存的(有碰撞的)key比較多,然後將新key儲存在負載少的位置。如果兩邊一樣多,比如兩個位置都為空或者都儲存了一個key,就把新key 儲存在左邊的T1子表中,2-left也由此而來。在查詢一個key時,必須進行兩次hash,同時查詢兩個位置。 

問題例項: 
1).海量日誌資料,提取出某日訪問百度次數最多的那個IP。 

IP的數目還是有限的,最多2^32個,所以可以考慮使用hash將ip直接存入記憶體,然後進行統計。 

3.bit-map 

適用範圍:可進行資料的快速查詢,判重,刪除,一般來說資料範圍是int的10倍以下 

基本原理及要點:使用bit陣列來表示某些元素是否存在,比如8位電話號碼 

擴充套件:bloom filter可以看做是對bit-map的擴充套件 

問題例項: 

1)已知某個檔案內包含一些電話號碼,每個號碼為8位數字,統計不同號碼的個數。 

8位最多99 999 999,大概需要99m個bit,大概10幾m位元組的記憶體即可。 

2)2.5億個整數中找出不重複的整數的個數,記憶體空間不足以容納這2.5億個整數。 

將bit-map擴充套件一下,用2bit表示一個數即可,0表示未出現,1表示出現一次,2表示出現2次及以上。或者我們不用2bit來進行表示,我們用兩個bit-map即可模擬實現這個2bit-map。 

4.堆 

適用範圍:海量資料前n大,並且n比較小,堆可以放入記憶體 

基本原理及要點:最大堆求前n小,最小堆求前n大。方法,比如求前n小,我們比較當前元素與最大堆裡的最大元素,如果它小於最大元素,則應該替換那個最大元素。這樣最後得到的n個元素就是最小的n個。適合大資料量,求前n小,n的大小比較小的情況,這樣可以掃描一遍即可得到所有的前n元素,效率很高。 

擴充套件:雙堆,一個最大堆與一個最小堆結合,可以用來維護中位數。 

問題例項: 
1)100w個數中找最大的前100個數。 

用一個100個元素大小的最小堆即可。 

5.雙層桶劃分 ----其實本質上就是【分而治之】的思想,重在“分”的技巧上! 

適用範圍:第k大,中位數,不重複或重複的數字 

基本原理及要點:因為元素範圍很大,不能利用直接定址表,所以通過多次劃分,逐步確定範圍,然後最後在一個可以接受的範圍內進行。可以通過多次縮小,雙層只是一個例子。 

擴充套件: 

問題例項: 
1).2.5億個整數中找出不重複的整數的個數,記憶體空間不足以容納這2.5億個整數。 

有點像鴿巢原理,整數個數為2^32,也就是,我們可以將這2^32個數,劃分為2^8個區域(比如用單個檔案代表一個區域),然後將資料分離到不同的區域,然後不同的區域在利用bitmap就可以直接解決了。也就是說只要有足夠的磁碟空間,就可以很方便的解決。 

2).5億個int找它們的中位數。 

這個例子比上面那個更明顯。首先我們將int劃分為2^16個區域,然後讀取資料統計落到各個區域裡的數的個數,之後我們根據統計結果就可以判斷中位數落到那個區域,同時知道這個區域中的第幾大數剛好是中位數。然後第二次掃描我們只統計落在這個區域中的那些數就可以了。 

實際上,如果不是int是int64,我們可以經過3次這樣的劃分即可降低到可以接受的程度。即可以先將int64分成2^24個區域,然後確定區域的第幾大數,在將該區域分成2^20個子區域,然後確定是子區域的第幾大數,然後子區域裡的數的個數只有2^20,就可以直接利用direct addr table進行統計了。 

6.資料庫索引 

適用範圍:大資料量的增刪改查 

基本原理及要點:利用資料的設計實現方法,對海量資料的增刪改查進行處理。 
擴充套件: 
問題例項: 


7.倒排索引(Inverted index) 

適用範圍:搜尋引擎,關鍵字查詢 

基本原理及要點:為何叫倒排索引?一種索引方法,被用來儲存在全文搜尋下某個單詞在一個文件或者一組文件中的儲存位置的對映。 

以英文為例,下面是要被索引的文字: 
T0 = "it is what it is" 
T1 = "what is it" 
T2 = "it is a banana" 
我們就能得到下面的反向檔案索引: 
"a": {2} 
"banana": {2} 
"is": {0, 1, 2} 
"it": {0, 1, 2} 
"what": {0, 1} 
檢索的條件"what", "is" 和 "it" 將對應集合的交集。 

正向索引開發出來用來儲存每個文件的單詞的列表。正向索引的查詢往往滿足每個文件有序頻繁的全文查詢和每個單詞在校驗文件中的驗證這樣的查詢。在正向索引中,文件佔據了中心的位置,每個文件指向了一個它所包含的索引項的序列。也就是說文件指向了它包含的那些單詞,而反向索引則是單詞指向了包含它的文件,很容易看到這個反向的關係。 

擴充套件: 

問題例項:文件檢索系統,查詢那些檔案包含了某單詞,比如常見的學術論文的關鍵字搜尋。 

8.外排序

適用範圍:大資料的排序,去重 

基本原理及要點:外排序的歸併方法,置換選擇 敗者樹原理,最優歸併樹 

擴充套件: 

問題例項: 
1).有一個1G大小的一個檔案,裡面每一行是一個詞,詞的大小不超過16個位元組,記憶體限制大小是1M。返回頻數最高的100個詞。 

這個資料具有很明顯的特點,詞的大小為16個位元組,但是記憶體只有1m做hash有些不夠,所以可以用來排序。記憶體可以當輸入緩衝區使用。 

9.trie樹 

適用範圍:資料量大,重複多,但是資料種類小可以放入記憶體 

基本原理及要點:實現方式,節點孩子的表示方式 

擴充套件:壓縮實現。 

問題例項: 
1).有10個檔案,每個檔案1G, 每個檔案的每一行都存放的是使用者的query,每個檔案的query都可能重複。要你按照query的頻度排序 。 

2).1000萬字符串,其中有些是相同的(重複),需要把重複的全部去掉,保留沒有重複的字串。請問怎麼設計和實現? 

3).尋找熱門查詢:查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個,每個不超過255位元組。 

10.分散式處理 mapreduce 

適用範圍:資料量大,但是資料種類小可以放入記憶體 

基本原理及要點:將資料交給不同的機器去處理,資料劃分,結果歸約。 

擴充套件: 

問題例項: 

1).The canonical example application of MapReduce is a process to count the appearances of 

each different word in a set of documents: 
void map(String name, String document): 
// name: document name 
// document: document contents 
for each word w in document: 
EmitIntermediate(w, 1); 

void reduce(String word, Iterator partialCounts): 
// key: a word 
// values: a list of aggregated partial counts 
int result = 0; 
for each v in partialCounts: 
result += ParseInt(v); 
Emit(result); 
Here, each document is split in words, and each word is counted initially with a "1" value by 

the Map function, using the word as the result key. The framework puts together all the pairs 

with the same key and feeds them to the same call to Reduce, thus this function just needs to 

sum all of its input values to find the total appearances of that word. 

2).海量資料分佈在100臺電腦中,想個辦法高效統計出這批資料的TOP10。 

3).一共有N個機器,每個機器上有N個數。每個機器最多存O(N)個數並對它們操作。如何找到N^2個數的中數(median)? 


經典問題分析 

上千萬or億資料(有重複),統計其中出現次數最多的前N個數據,分兩種情況:可一次讀入記憶體,不可一次讀入。 

可用思路:trie樹+堆,資料庫索引,劃分子集分別統計,hash,分散式計算,近似統計,外排序 

所謂的是否能一次讀入記憶體,實際上應該指去除重複後的資料量。如果去重後資料可以放入記憶體,我們可以為資料建立字典,比如通過 map,hashmap,trie,然後直接進行統計即可。當然在更新每條資料的出現次數的時候,我們可以利用一個堆來維護出現次數最多的前N個數據,當然這樣導致維護次數增加,不如完全統計後在求前N大效率高。 

如果資料無法放入記憶體。一方面我們可以考慮上面的字典方法能否被改進以適應這種情形,可以做的改變就是將字典存放到硬碟上,而不是記憶體,這可以參考資料庫的儲存方法。 

當然還有更好的方法,就是可以採用分散式計算,基本上就是map-reduce過程,首先可以根據資料值或者把資料hash(md5)後的值,將資料按照範圍劃分到不同的機子,最好可以讓資料劃分後可以一次讀入記憶體,這樣不同的機子負責處理各種的數值範圍,實際上就是map。得到結果後,各個機子只需拿出各自的出現次數最多的前N個數據,然後彙總,選出所有的資料中出現次數最多的前N個數據,這實際上就是reduce過程。 

實際上可能想直接將資料均分到不同的機子上進行處理,這樣是無法得到正確的解的。因為一個數據可能被均分到不同的機子上,而另一個則可能完全聚集到一個機子上,同時還可能存在具有相同數目的資料。比如我們要找出現次數最多的前100個,我們將1000萬的資料分佈到10臺機器上,找到每臺出現次數最多的前 100個,歸併之後這樣不能保證找到真正的第100個,因為比如出現次數最多的第100個可能有1萬個,但是它被分到了10臺機子,這樣在每臺上只有1千個,假設這些機子排名在1000個之前的那些都是單獨分佈在一臺機子上的,比如有1001個,這樣本來具有1萬個的這個就會被淘汰,即使我們讓每臺機子選出出現次數最多的1000個再歸併,仍然會出錯,因為可能存在大量個數為1001個的發生聚集。因此不能將資料隨便均分到不同機子上,而是要根據hash 後的值將它們對映到不同的機子上處理,讓不同的機器處理一個數值範圍。 

而外排序的方法會消耗大量的IO,效率不會很高。而上面的分散式方法,也可以用於單機版本,也就是將總的資料根據值的範圍,劃分成多個不同的子檔案,然後逐個處理。處理完畢之後再對這些單詞的及其出現頻率進行一個歸併。實際上就可以利用一個外排序的歸併過程。 

相關推薦

php 料量海量資料處理演算法總結

下面的方法是我對海量資料的處理方法進行了一個一般性的總結,當然這些方法可能並不能完全覆蓋所有的問題,但是這樣的一些方法也基本可以處理絕大多數遇到的問題。下面的一些問題基本直接來源於公司的面試筆試題目,方法不一定最優,如果你有更好的處理方法,歡迎與我討論。 1.Bloom f

料量海量資料處理方法總結

大資料量的問題是很多面試筆試中經常出現的問題,比如baidu google 騰訊這樣的一些涉及到海量資料的公司經常會問到。 下面的方法是我對海量資料的處理方法進行了一個一般性的總結,當然這些方法可能並不能完全覆蓋所有的問題,但是這樣的一些方法也基本

海量資料處理演算法總結【超詳解】

【Bloom Filter】Bloom Filter(BF)是一種空間效率很高的隨機資料結構,它利用位陣列很簡潔地表示一個集合,並能判斷一個元素是否屬於這個集合。它是一個判斷元素是否存在集合的快速的概率演算法。Bloom Filter有可能會出現錯誤判斷,但不會漏掉判斷。也就是Bloom Filter判斷元素

海量資料處理:十道面試題與十個海量資料處理方法總結資料演算法面試題)

第一部分、十道海量資料處理面試題 1、海量日誌資料,提取出某日訪問百度次數最多的那個IP。       首先是這一天,並且是訪問百度的日誌中的IP取出來,逐個寫入到一個大檔案中。注意到IP是32位的,最多有個2^32個IP。同樣可以採用對映的方法

POI3.8中 料量的excel表格處理

POI之前的版本不支援大資料量處理,如果資料過多則經常報OOM錯誤,有時候調整JVM大小效果也不是太好。3.8版本的POI新出來了SXSSFWorkbook,可以支援大資料量的操作。 3.8版本的PO

oracle中造料量的測試資料

CREATE     TABLE TEST_EXPORT NOLOGGING PARALLEL 4 AS SELECT     LEVEL           AS ID,     LEVEL||'NAME'   AS NAME,     LEVEL||'REMARK' A

海量資料處理演算法—Bit-Map

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

海量資料處理:十道面試題與十個海量資料處理方法總結

第一部分、十道海量資料處理面試題 1、海量日誌資料,提取出某日訪問百度次數最多的那個IP。 首先是這一天,並且是訪問百度的日誌中的IP取出來,逐個寫入到一個大檔案中。注意到IP是32位的,最多有個2^32個IP。同樣可以採用對映的方法,比如模1000,把整個大檔

海量資料處理演算法—Bloom Filter

                1. Bloom-Filter演算法簡介        Bloom-Filter,即布隆過濾器,1970年由Bloom中提出。它可以用於檢索一個元素是否在一個集合中。Bloom Filter(BF)是一種空間效率很高的隨機資料結構,它利用位陣列很簡潔地表示一個集合,並能判斷一個

影象資料處理演算法總結

本博文主要介紹了影象處理的一些基礎知識 一. 影象儲存原理 影象儲存原理主要分為5種 1. RGB顏色空間,使用最為廣泛的顏色空間。 2. CMY(K)顏色空間,主要用於印刷行業。 3. HSV/HSL(I)顏色空間,人類視覺,和畫家配色領域。 4. CIE-XYZ顏色空間,

java專案——料量處理 標籤: 資料記憶體儲存

15. 最大間隙問題  給定n個實數 ,求著n個實數在實軸上向量2個數之間的最大差值,要求線性的時間演算法。  方案1:最先想到的方法就是先對這n個數據進行排序,然後一遍掃描即可確定相鄰的最大間隙。但該方法不能滿足線性時間的要求。故採取如下方法:  s 找到n個數據中最大和最小資料max和min。  s 用n

資料新增非同步解析重新整理料量redis (——)(五)redisutils

首先要在配置檔案注入這個bean     這也是我非同步重新整理獲取bean用的redisutils工具類: import javax.servlet.ServletContext; import javax.servlet.http.HttpServl

資料新增非同步解析重新整理料量redis (——)(四)非同步重新整理reids主

重新整理redis方法的bean: public class MethodAndParameter {     private String methodName;//方法名          pr

資料新增非同步解析重新整理料量redis (——)(三)Spring Boot普通類呼叫bean【從零開始學Spring Boot】

部落格分類:  從零開始學Spring Boot 從零開始學Spring BootSpring Boot普通類呼叫bean    【視訊&交流平臺】 à SpringBoot視訊 http://stu

資料新增非同步解析重新整理料量redis (——)(二) SpringBoot之CommandLineRunner介面和ApplicationRunner介面

在spring boot應用中,我們可以在程式啟動之前執行任何任務。為了達到這個目的,我們需要使用CommandLineRunner或ApplicationRunner介面建立bean,spring boot會自動監測到它們。這兩個介面都有一個run()方法,在實現介面時需要覆蓋該方法,並使用@

資料新增非同步解析重新整理料量redis (——)(一)Java Collection之Queue佇列

Queue介面與List、Set同一級別,都是繼承了Collection介面。LinkedList實現了Queue接 口。Queue介面窄化了對LinkedList的方法的訪問許可權(即在方法中的引數型別如果是Queue時,就完全只能訪問Queue介面所定義的方法 了,而不能直接訪問 Linke

料量單表在不同表名列名間的資料遷移

(windows Server 2008 R2+oracle 11g) 單表資料1.5億條記錄,90個欄位,檔案大小70G 處理思路:源端單表exp,目標端單表imp,再通過欄位對應關係轉入到目標表(不同表名、列名) exp username1/password1 buffer=6400

料量表的查詢優化索引使用

一、對於運算邏輯,儘可能將要統計的各專案整合在一個查詢語句中計算,而不是用分組條件或分專案呼叫多個查詢語句,而後在程式碼裡計算結果。 二、查詢語句的優化,諸如不用"select *"、多表關聯查詢時新增別名於查詢欄位上、避免使用in、not in關鍵字、非去除重複時用union all替換uni

十道海量資料處理面試題與十個方法總結

轉載之處:http://blog.csdn.net/liuqiyao_01/article/details/26567237 筆試 = (資料結構+演算法) 50%+ (計算機網路 + 作業系統)30% +邏輯智力題10%  + 資料庫5% + 歪門邪道題5%,而面

JDK8 switch使用字串比if else 效率高,親測料量資料

for (TemplateFormVO templateFormVO:templateFormVOS){ formid=String.valueOf(templateFormVO.getFormId()); formId=templateFormVO.getFormI