Bit map法處理大資料問題

2021-07-22 23:25:35 字數 4076 閱讀 5550

問題引入:

1.給40億個不重複的unsigned int的整數,沒排過序的,然後再給乙個數,如何快速判斷這個數是否在那40億個數當中?

2.給定乙個千萬級別資料量的整數集合,判斷哪些是重複元素。

3.給定乙個千萬級別資料量的整形陣列,對其進行排序。

4.在5億個整數中找出不重複的整數(注意,假設記憶體不足以容納這5億個整數)。

從資料量上看,使用常規的解法(普通排序演算法,逐個比較等)明顯不合適,所以這裡我們引入乙個新的解法,就是bitmap。

bitmap就是用乙個bit位來標記某個元素對應的value, 而key即是該bit的位序。由於採用了bit為單位來儲存資料,因此可以大大節省儲存空間。 bitmap通過1個位表示乙個狀態,比如:int型別有2^32個數字,即4g個數字,那麼每個數字乙個狀態,就是2^32個bit,即512 mb(也就是說,用512兆儲存空間就可以處理4g個資料,即40+億資料)。

下面是我用c++寫的乙個bitmap類,可以通過構造物件時傳入資料規模,動態申請所需的記憶體,然後處理使用者的大量資料:

1 #include2 #include3 #include4

using

namespace

std;

5const unsigned size = 512000000;//

512兆靜態儲存區可處理40.96億資料67

class

bitmap

15//

設定該位,就是儲存該數

16void

set1(unsigned at)

1720

//讀取該位是否有數

21bool

get1(unsigned at)

2225

} byte;

26 byte *m_byte;

27unsigned m_size;

28public:29

bitmap(unsigned _size)

3034

virtual ~bitmap()

3539

//儲存乙個資料

40bool

push(unsigned data)

4147

//讀取乙個資料是否存在

48bool

find(unsigned data)

4952

//返回能儲存的資料個數

53unsigned size()

5457

//過載運算子實現常用功能

58//

儲存乙個資料

59bool

operator>>(unsigned data)

6063

//讀取乙個資料是否存在

64bool

operator

<

6568

//訪問到某個資料塊

69 byte& operator

(unsigned i)

7075

};76

const unsigned char bitmap::byte::mask[9] = ;//

用來取得乙個位元組每一位的輔助陣列

7778

intmain()

79102

return0;

103 }

執行結果如下:

在程式中,先讀取乙個文字檔案中隨機產生的6w個整數,存到這個bitmap中,然後測試了一下從這個建立好的bitmap中查詢100w資料耗時情況(11ms左右),接下來的部分是使用者可以手動輸入一些整數,程式會自動檢索bitmap中是否已儲存該資料。

這樣就可以解決引入話題中的第乙個問題了,把輸入的文字資料改為已知的40億資料就可以了(40億資料的錄入可能需要一會兒,大概1300秒)。

下面給出引入的剩餘三個問題的解題思路。

問題2:先建立乙個足夠大的bitmap物件,然後依次錄入這些資料,如果錄入某資料前發現該位已經為1,則該資料重複,依次得到重複的資料即可。

問題3:先建立乙個足夠大的bitmap物件,然後依次錄入這些資料,從bitmap開始位置起遍歷,如果某位不為0,則表示有該資料,依次輸出不為0的位的位序就是排序好的陣列(輸出太多沒意義,可以將輸出轉換到寫入檔案,那麼新檔案中資料就是排序好的)。

問題4方法1,建立2個足夠大的bitmap物件,依次錄入資料,錄入前先判斷該資料在bitmap1中是否存在(即對應位是否為1),不存在則錄入到bitmap1中,存在就錄入到bitmap2中;全部錄入完後,依次遍歷bitmap1中每一位,如果某一位為1但是bitmap2中對應位不為1,則表示該資料只出現過一次,依次輸出即可。

方法2,建立乙個足夠大的bitmap物件,不過用兩位表示乙個資料,00表示資料不存在,01資料出現一次,10表示資料出現多次。11呢?一邊涼快去吧,不要你了,哈哈。這樣依次錄入資料時,如果該對應位(其實是兩位)為00則改為01,01就改為10,10就不管了。錄入完成後,遍歷整個bitmap,找到01位就輸出。

——————————————————————————————我是分割線—————————————————————————————

好了,常見的大資料題目就通過bitmap這個神奇的結構給解決了,不過bitmap也不是萬能的,很明顯,它暫時只適合儲存整形資料,當然這裡只考慮了unsigned型別資料,如果是int型別的話,對應對映一下就可以了也是沒問題的。不過即使如此,也只能處理10億級別的資料,如果資料量更大、型別不只是整形呢?

比如:需要寫乙個網路蜘蛛(web crawler)。由於網路間的鏈結錯綜複雜,蜘蛛在網路間爬行很可能會形成「環」。為了避免形成「環」,就需要知道蜘蛛已經訪問過哪那些url。給乙個url,怎樣知道蜘蛛是否已經訪問過?

不難想到如下幾種方案:

1. 將訪問過的url全部儲存到資料庫;

2. 用hashset將訪問過的url儲存起來。那只需接近o(1)的代價就可以查到乙個url是否被訪問過;

3. url經過md5或sha-1等單向雜湊後再儲存到hashset或資料庫。

4. bit-map方法。建立乙個bitset,將每個url經過乙個雜湊函式對映到某一位。

方法1~3都是將訪問過的url完整儲存,方法4則只標記url的乙個對映位。

以上方法在資料量較小的情況下都能完美解決問題,但是當資料量變得非常龐大時問題就來了。

方法1:資料量變得非常龐大後關係型資料庫查詢的效率會變得很低。而且每來乙個url就啟動一次資料庫查詢是不是太小題大做了?

方法2:太消耗記憶體。隨著url的增多,占用的記憶體會越來越多。就算只有1億個url,每個url只算50個字元,就需要5gb記憶體。

方法3:由於字串經過md5處理後的資訊摘要長度只有128bit,sha-1處理後也只有160bit,因此方法3比方法2節省了好幾倍的記憶體。

方法4:消耗記憶體是相對較少的,但缺點是單一雜湊函式發生衝突的概率太高。還記得資料結構課上學過的hash表衝突的各種解決方法麼?若要降低衝突發生的概率到1%,就要將bitset的長度設定為url個數的100倍。

但是我們可以考慮如果在一定程度上忽略誤判的情況,那麼是不是可以通過改進方法4實現這一功能?其實這就是bloom filter的演算法的思想:bloom filter是由bloom在2023年提出的一種多雜湊函式對映的快速查詢演算法。通常應用在一些需要快速判斷某個元素是否屬於集合,但是並不嚴格要求100%正確的場合。其思想就是在方法4基礎上做了一些改進,不是對映到一位,而是通過k個雜湊函式對映到k位上,這樣只有當新的url計算得到的k位都為1時才判斷為該url已經訪問過(有誤判的可能性,不過有相關研究證明,取得合適的k值和bitmap位數時可以讓誤判率很小以至於可以忽略,參見細節)

當然,還可以通過map-reduce來處理,畢竟人家mapreduce可是行家,專業的大資料處理技術嘛!

bitmap位圖法

bloomfilter——大規模資料處理利器

bloomfilter概念及原理 

大資料處理 Bitmap

mapreduce是一種程式設計模型,用於大規模資料集 大於1tb 的並行運算。概念 map 對映 和 reduce 歸約 bit map空間壓縮和快速排序去重 1.bit map的基本思想 32位機器上,對於乙個整型數,比如int a 1 在記憶體中佔32bit位,這是為了方便計算機的運算。但是對...

bitmap處理海量資料

什麼是bit map 所謂的bit map就是用乙個bit位來標記某個元素對應的value,而key即是該元素。由於採用了bit為單位來儲存資料,因此在儲存空間方面,可以大大節省。如果說了這麼多還沒明白什麼是bit map,那麼我們來看乙個具體的例子,假設我們要對0 7內的5個元素 4,7,2,5,...

bit map海量資料處理

海量資料排序問題 檔案包含1千萬條 號碼記錄 10 7次方 每條記錄都是7位整數,沒有重複的整數。要求對檔案進行排序,注意大約只有1mb的記憶體空間可用,有充足的磁碟儲存空間可用。請設計乙個高效的演算法。1 運用多趟演算法 如果每個號碼都使用32位整數來表示,則在1mb儲存空間裡大約可以存25000...