Ⅰ bitmap能存放的最大數據是多少
redis的bitmap能設置最大的長度是多少, 為什麼可以設置的最大長度位數是2^32, 怎麼計算bitmap會佔用多大的空間
前提: 實際上, redis只支持5種數據類型. 並沒有bitmap. 也就是bitmap是基於redis的字元串類型的. 而一個字元串類型最多存儲512M.
首先: 計算機的單位換算先了解下
8 bit = 1byte
1024 byte = 1kb
1024 kb = 1Mb
其次:
我們使用的bitmap指令SETBIT key offset value, 這個指令就是將第offset設置成0或1. 比如 SETBIT ss 1000 1 //就是將1000位置為1. 1 bit就是1位, 所以我們只要將512M換算成bit, 那麼就知道bitmap支持的最大設置長度了. 計算如下
8 * 1024 * 1024 * 512 = 2^32 (所以這個結果就是這么來的)
怎麼計算自己的bitmap會大概佔用多大的存儲空間呢?
舉個栗子: 今有一個bitmap最大長度1024, 需要佔用多大的空間?
解: 長度1024也就是他需要1024個位(bit), 或者單位為byte就是需要 1024 / 8, 即需要128byte
————————————————
版權聲明:本文為CSDN博主「Day____Day____Up」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_37281289/article/details/106834014
Ⅱ 大數據排序或取重或去重相關問題
大數據排序或取重或去重相關問題
1. 給定a、b兩個文件,各存放50億個url,每個url各佔64位元組,內存限制是4G,讓你找出a、b文件共同的url?
方案1:可以估計每個文件安的大小為50G×64=320G,遠遠大於內存限制的4G。所以不可能將其完全載入到內存中處理。考慮採取分而治之的方法。
s 遍歷文件a,對每個url求取 ,然後根據所取得的值將url分別存儲到1000個小文件(記為 )中。這樣每個小文件的大約為300M。
s 遍歷文件b,採取和a相同的方式將url分別存儲到1000各小文件(記為 )。這樣處理後,所有可能相同的url都在對應的小文件( )中,不對應的小文件不可能有相同的url。然後我們只要求出1000對小文件中相同的url即可。
s 求每對小文件中相同的url時,可以把其中一個小文件的url存儲到hash_set中。然後遍歷另一個小文件的每個url,看其是否在剛才構建的hash_set中,如果是,那麼就是共同的url,存到文件裡面就可以了。
方案2:如果允許有一定的錯誤率,可以使用Bloom filter,4G內存大概可以表示340億bit。將其中一個文件中的url使用Bloom filter映射為這340億bit,然後挨個讀取另外一個文件的url,檢查是否與Bloom filter,如果是,那麼該url應該是共同的url(注意會有一定的錯誤率)。
2. 有10個文件,每個文件1G,每個文件的每一行存放的都是用戶的query,每個文件的query都可能重復。要求你按照query的頻度排序。 方案1:
s 順序讀取10個文件,按照hash(query)%10的結果將query寫入到另外10個文件(記為 )中。這樣新生成的文件每個的大小大約也1G(假設hash函數是隨機的)。
s 找一台內存在2G左右的機器,依次對 用hash_map(query, query_count)來統計每個query出現的次數。利用快速/堆/歸並排序按照出現次數進行排序。將排序好的query和對應的query_cout輸出到文件中。這樣得到了10個排好序的文件(記為 )。
s 對 這10個文件進行歸並排序(內排序與外排序相結合)。
方案2:
一般query的總量是有限的,只是重復的次數比較多而已,可能對於所有的query,一次性就可以加入到內存了。這樣,我們就可以採用trie樹/hash_map等直接來統計每個query出現的次數,然後按出現次數做快速/堆/歸並排序就可以了。
方案3:
與方案1類似,但在做完hash,分成多個文件後,可以交給多個文件來處理,採用分布式的架構來處理(比如MapRece),最後再進行合並。
3. 有一個1G大小的一個文件,裡面每一行是一個詞,詞的大小不超過16位元組,內存限制大小是1M。返回頻數最高的100個詞。
方案1:順序讀文件中,對於每個詞x,取 ,然後按照該值存到5000個小文件(記為 ) 中。這樣每個文件大概是200k左右。如果其中的有的文件超過了1M大小,還可以按照類似的方法繼續往下分,知道分解得到的小文件的大小都不超過1M。對每個小文件,統計每個文件中出現的詞以及相應的頻率(可以採用trie樹/hash_map等),並取出出現頻率最大的100個詞(可以用含100個結點 的最小堆),並把100詞及相應的頻率存入文件,這樣又得到了5000個文件。下一步就是把這5000個文件進行歸並(類似與歸並排序)的過程了。
4. 海量日誌數據,提取出某日訪問網路次數最多的那個IP。
方案1:首先是這一天,並且是訪問網路的日誌中的IP取出來,逐個寫入到一個大文件中。注意到IP是32位的,最多有 個 IP。同樣可以採用映射的方法,比如模1000,把整個大文件映射為1000個小文件,再找出每個小文中出現頻率最大的IP(可以採用hash_map進 行頻率統計,然後再找出頻率最大的幾個)及相應的頻率。然後再在這1000個最大的IP中,找出那個頻率最大的IP,即為所求。
5. 在2.5億個整數中找出不重復的整數,內存不足以容納這2.5億個整數。
方案1:採用2-Bitmap(每個數分配2bit,00表示不存在,01表示出現一次,10表示多次,11無意義)進行,共需內存內存,還可以接受。然後掃描這2.5億個整數,查看Bitmap中相對應位,如果是00變01,01變10,10保持不變。所描完事後,查看bitmap,把對應位是01的整數輸出即可。
方案2:也可採用上題類似的方法,進行劃分小文件的方法。然後在小文件中找出不重復的整數,並排序。然後再進行歸並,注意去除重復的元素。
6. 海量數據分布在100台電腦中,想個辦法高校統計出這批數據的TOP10。
方案1:
s 在每台電腦上求出TOP10,可以採用包含10個元素的堆完成(TOP10小,用最大堆,TOP10大,用最小堆)。比如求TOP10大,我們首先取前10個元素調整成最小堆,如果發現,然後掃描後面的數據,並與堆頂元素比較,如果比堆頂元素大,那麼用該元素替換堆頂,然後再調整為最小堆。最後堆中的元 素就是TOP10大。
s 求出每台電腦上的TOP10後,然後把這100台電腦上的TOP10組合起來,共1000個數據,再利用上面類似的方法求出TOP10就可以了。
7. 怎麼在海量數據中找出重復次數最多的一個?
方案1:先做hash,然後求模映射為小文件,求出每個小文件中重復次數最多的一個,並記錄重復次數。然後找出上一步求出的數據中重復次數最多的一個就是所求(具體參考前面的題)。
8. 上千萬或上億數據(有重復),統計其中出現次數最多的錢N個數據。
方案1:上千萬或上億的數據,現在的機器的內存應該能存下。所以考慮採用hash_map/搜索二叉樹/紅黑樹等來進行統計次數。然後就是取出前N個出現次數最多的數據了,可以用第6題提到的堆機制完成。
9. 1000萬字元串,其中有些是重復的,需要把重復的全部去掉,保留沒有重復的字元串。請怎麼設計和實現?
方案1:這題用trie樹比較合適,hash_map也應該能行。
10. 一個文本文件,大約有一萬行,每行一個詞,要求統計出其中最頻繁出現的前10個詞,請給出思想,給出時間復雜度分析。
方案1:這題是考慮時間效率。用trie樹統計每個詞出現的次數,時間復雜度是O(n*le)(le表示單詞的平準長度)。然後是找出出現最頻繁的前10個詞,可以用堆來實現,前面的題中已經講到了,時間復雜度是O(n*lg10)。所以總的時間復雜度,是O(n*le)與O(n*lg10)中較大 的哪一個。
11. 一個文本文件,找出前10個經常出現的詞,但這次文件比較長,說是上億行或十億行,總之無法一次讀入內存,問最優解。
方案1:首先根據用hash並求模,將文件分解為多個小文件,對於單個文件利用上題的方法求出每個文件件中10個最常出現的詞。然後再進行歸並處理,找出最終的10個最常出現的詞。
12. 100w個數中找出最大的100個數。
方案1:在前面的題中,我們已經提到了,用一個含100個元素的最小堆完成。復雜度為O(100w*lg100)。
方案2:採用快速排序的思想,每次分割之後只考慮比軸大的一部分,知道比軸大的一部分在比100多的時候,採用傳統排序演算法排序,取前100個。復雜度為O(100w*100)。
方案3:採用局部淘汰法。選取前100個元素,並排序,記為序列L。然後一次掃描剩餘的元素x,與排好序的100個元素中最小的元素比,如果比這個最小的要大,那麼把這個最小的元素刪除,並把x利用插入排序的思想,插入到序列L中。依次循環,知道掃描了所有的元素。復雜度為O(100w*100)。
13. 尋找熱門查詢:
搜索引擎會通過日誌文件把用戶每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255位元組。假設目前有一千萬個記錄,這些查詢串的重復讀比較高,雖然總數是1千萬,但是如果去除重復和,不超過3百萬個。一個查詢串的重復度越高,說明查詢它的用戶越多,也就越熱門。請你統計最熱門的10個 查詢串,要求使用的內存不能超過1G。
(1) 請描述你解決這個問題的思路;
(2) 請給出主要的處理流程,演算法,以及演算法的復雜度。
方案1:採用trie樹,關鍵字域存該查詢串出現的次數,沒有出現為0。最後用10個元素的最小推來對出現頻率進行排序。
14. 一共有N個機器,每個機器上有N個數。每個機器最多存O(N)個數並對它們操作。如何找到 個數中的中數?
方案1:先大體估計一下這些數的范圍,比如這里假設這些數都是32位無符號整數(共有 個)。我們把0到 的整數劃分為N個范圍段,每個段包含 個整數。比如,第一個段位0到 ,第二段為 到 ,…,第N個段為 到 。 然後,掃描每個機器上的N個數,把屬於第一個區段的數放到第一個機器上,屬於第二個區段的數放到第二個機器上,…,屬於第N個區段的數放到第N個機器上。 注意這個過程每個機器上存儲的數應該是O(N)的。下面我們依次統計每個機器上數的個數,一次累加,直到找到第k個機器,在該機器上累加的數大於或等於 ,而在第k-1個機器上的累加數小於 ,並把這個數記為x。那麼我們要找的中位數在第k個機器中,排在第 位。然後我們對第k個機器的數排序,並找出第 個數,即為所求的中位數。復雜度是 的。
方案2:先對每台機器上的數進行排序。排好序後,我們採用歸並排序的思想,將這N個機器上的數歸並起來得到最終的排序。找到第n個便是所求。復雜度是n(i)的。
15. 最大間隙問題
給定n個實數 ,求著n個實數在實軸上向量2個數之間的最大差值,要求線性的時間演算法。
方案1:最先想到的方法就是先對這n個數據進行排序,然後一遍掃描即可確定相鄰的最大間隙。但該方法不能滿足線性時間的要求。故採取如下方法:
s 找到n個數據中最大和最小數據max和min。
s 用n-2個點等分區間[min, max],即將[min, max]等分為n-1個區間(前閉後開區間),將這些區間看作桶,編號為 ,且桶 的上界和桶i+1的下屆相同,即每個桶的大小相同。每個桶的大小為: 。實際上,這些桶的邊界構成了一個等差數列(首項為min,公差為 ),且認為將min放入第一個桶,將max放入第n-1個桶。
s 將n個數放入n-1個桶中:將每個元素 分配到某個桶(編號為index),其中 ,並求出分到每個桶的最大最小數據。
s最大間隙:除最大最小數據max和min以外的n-2個數據放入n-1個桶中,由抽屜原理可知至少有一個桶是空的,又因為每個桶的大小相同,所以最大間隙不會在同一桶中出現,一定是某個桶的上界和氣候某個桶的下界之間隙,且該量筒之間的桶(即便好在該連個便好之間的桶)一定是空桶。也就是說,最大間隙在桶 i的上界和桶j的下界之間產生 。一遍掃描即可完成。
16. 將多個集合合並成沒有交集的集合:給定一個字元串的集合,格式如: 。要求將其中交集不為空的集合合並,要求合並完成的集合之間無交集,例如上例應輸出 。
(1) 請描述你解決這個問題的思路;
(2) 給出主要的處理流程,演算法,以及演算法的復雜度;
(3) 請描述可能的改進。
方案1:採用並查集。首先所有的字元串都在單獨的並查集中。然後依掃描每個集合,順序合並將兩個相鄰元素合並。例如,對於 , 首先查看aaa和bbb是否在同一個並查集中,如果不在,那麼把它們所在的並查集合並,然後再看bbb和ccc是否在同一個並查集中,如果不在,那麼也把它們所在的並查集合並。接下來再掃描其他的集合,當所有的集合都掃描完了,並查集代表的集合便是所求。復雜度應該是O(NlgN)的。改進的話,首先可以 記錄每個節點的根結點,改進查詢。合並的時候,可以把大的和小的進行合,這樣也減少復雜度。
17. 最大子序列與最大子矩陣問題
數組的最大子序列問題:給定一個數組,其中元素有正,也有負,找出其中一個連續子序列,使和最大。
方案1:這個問題可以動態規劃的思想解決。設 表示以第i個元素 結尾的最大子序列,那麼顯然 。基於這一點可以很快用代碼實現。
最大子矩陣問題:給定一個矩陣(二維數組),其中數據有大有小,請找一個子矩陣,使得子矩陣的和最大,並輸出這個和。
方案1:可以採用與最大子序列類似的思想來解決。如果我們確定了選擇第i列和第j列之間的元素,那麼在這個范圍內,其實就是一個最大子序列問題。如何確定第i列和第j列可以詞用暴搜的方法進行。
Ⅲ 在Android開發中,有哪些好的內存優化方式
你好,要優化內存有很多方法
1:可以下載內存優化軟體,例如獵豹安全大師,360清潔大師,91助手等等;
2:刪除或者卸載手機自帶不常用的軟體,例如在中國不適合使用谷歌,YouTube等等(前提是你要ROOT 手機)
3:注意某些軟體的後台運行,有些時候,軟體退出不代表就是真的退出,在後台它或許還在運行,要注意在設置尋找到應用程序管理器,找到後台運行軟體,將其關閉。
4:手機恢復出廠設置,這是最實用,最直接的辦法,但是要注意所有文件的備份,不然,一旦還原幾乎找不回來
Ⅳ Redis 大數據內存優化 (RoaringBitmap)
最近碰到手機設備匹配的業務, 用戶在我司後台可以上傳人群包, 裡面存放的是設備的MD5標識符; 一個人群包大概有千萬級的MD5數據, 與廣告請求所攜帶設備標識進行匹配.
嘗試插入1kw條數據, key為設備MD5值, value為1, 此時Redis中存在1kw條key-value鍵值對.
通過 info 指令查看內存佔用:
8bit = 1b = 0.001kb
bitmap即點陣圖, 就是通過最小的單位bit來進行0或者1的設置,表示某個元素對應的值或者狀態。
一個bit的值,或者是0,或者是1;也就是說一個bit能存儲的最多信息是2。
場景: 有用戶id分別為1, 2, 3, 4, 5, 6, 7, 8的用戶, 其中用戶2, 5在今日登錄, 統計今
日登錄用戶
採用點陣圖存儲: 用戶id為偏移量, 可以看做是在點陣圖中的索引, value為true
通過 bitcount 獲取登錄用戶數為2:
測試offset從1-1kw連續整數時候的內存佔用:
可以發現內存佔用僅為 1.19MB, 1個億的數據也才12MB, 極大的減少了內存;
由於我們的業務沒有如此完美的情況出現, 採用設備MD5的hash做Offset, 不會出現連續正整數的情況;
各常用Hash函數性能對比: https://byvoid.com/zhs/blog/string-hash-compare/
所以我們接下來測試1kw條MD5數據的點陣圖內存佔用:
查看Redis內存佔用:
問題: 為什麼同樣1kw的bitmap, MD5數據的Hash佔用會比 測試一 的多200倍?
將32位無符號整數按照高16位分桶,即最多可能有216=65536個桶,稱為container。存儲數據時,按照數據的高16位找到container(找不到就會新建一個),再將低16位放入container中。也就是說,一個RBM就是很多container的集合。
圖中示出了三個container:
1kw條MD5數據的插入:
Ⅳ Android跨進程傳遞大數據
最近要從 Service 端給 Client 端傳遞圖片數據,之前的數據都是通過 aidl 傳遞:
創建 Parcelable 文件
ImageData.java
test.aidl
運行報錯:
這里導致 DeadObjectException 的原因主要是 binder 創建的 buffer 被占滿了:
傳輸中如果數據大於 free_buffers ,則會拋出 DeadObjectException
socke 傳輸不受大小限制,但實現比較復雜
通過文件傳輸比較簡單,但效率差,而且高版本會受到Android系統許可權限制
將較大數據切割成較小的數據傳輸,此方法是兼顧效率,復雜度較好的方案
定義數據體:
切割數據方法:
將ImageData按順序構建發送:
client接收:
binder 本身也是利用 mmap ,可以利用實現 mmap 的框架,比如 MMKV
如果傳輸的數據是 Bitmap ,還可以用 Bundle 的 putBinder 方案
定義 binder :
發送
接收:
Ⅵ BitMap及其在ClickHouse中的應用
問題要從面試或者大數據場景下最常見的一個演算法說起,問題是這樣的,假如有幾十億個unsigned int類型的數據,要求去重或者計算總共有多少不重復的數據?最簡單的辦法就是直接利用一個HashMap,進行去重。但是這裡面有個內存使用量的問題,幾十億個元素,即使不考慮HashMap本身實現所用到的數據結果,單單key本身,假如每個unsigned int佔用4個位元組,簡單算一下的話,這里都需要幾十GB的內存佔用,因此,這里就引出了BItMap。
BItMap的思想非常簡單,就是用一個bit表示一個二元的狀態,比如有或者沒有,存在或者不存在,用bit本身的位置信息,對應不同的數據。比如針對上面的問題,我們可以開辟一個2^32 bit的內存空間,每一個bit存儲一個unsigned int類型的數據,有就是1,沒有就是0,總共需要存儲unsigned int類型的最大范圍個數據,也就是2^32 個數據,這個2^32其實就是所謂的基數。如下圖所示:
假如存在數字8,那就把對應的第8位的值賦為1。上圖插入的數據為1、3、7、8。接著依次把所有的數據遍歷然後更新這個BitMap。這樣我們就可以得到最終結果。
假如上面的問題變成了對幾十億個URL做判斷,那應該怎麼去做呢?URL沒有辦法和BitMap的位置關系對應上,所以,我們需要加一層哈希,把每個URL經過哈希運算得到一個整數,然後對應上BitMap。如下圖所示:
但是有哈希,肯定會存在碰撞,如果BitMap基數(也就是長度)比較小,那碰撞的概率就大,如果基數比較大,那佔用的空間又會比較多。Bloom Filter的思想就是引入多個哈希函數來解決沖突的問題。也就是說對每個URL,經過多個哈希函數的運算,得到多個值,每個數值對應的BitMap的對應的位置都賦值為1。這個兩個URL經過多個哈希函數結果還是一樣的概率就大大降低。
但是由於依然存在沖突的可能性(其實沖突就是來源於我們BitMap的長度小於了數據量的基數,這也就是犧牲了准確性換來了空間使用的減少),所以Bloom Filter 存在假陽性的概率,不適用於任何要求 100% 准確率的場景,也就是說Bloom Filter 只能用來判無,不能用來判有。比如一個URL經過多次哈希運算之後,發現對應的BitMap的位置都已經是1了,那也不能說明,這個URL之前存在過了,也有可能是哈希沖突的結果。但是一個URL經過多次哈希運算之後,發現對應的BitMap的位置不是都是1,那當前URL之前一定是沒有存在過的。
可以看到,Bloom Filter 引入多次哈希,在查詢效率和插入效率不變的情況下,用較少空間的BitMap解決大數據量的判斷問題。
大部分情況下僅僅做有無的判斷是不能滿足使用需求的,我們還是需要真正意義上的BitMap(可以方便的用來做交並等計算),但是最好可以在基數比較大的時候,依然可以佔用相對比較小的空間。這就是RoaringBitMap所要實現的。
簡單來說RoaringBitMap是BitMap的一種帶索引的復雜BitMap數據結構。以32位的RoaringBitMap為例,首先劃分2^16 個空間(Container),每個Container內部都是一個大小為2^16 bit的BitMap,總的內存使用量還是2^32 = 512Mb。這樣的話和普通的BitMap是沒有區別的,而RoaringBitMap的創新之處在於每個Container內的BitMap是在沒有使用到的情況下是可以不分配內存空間的。這樣可以大大減小內存的使用量。
(這個圖片是Roaring Bitmaps: Implementation of an Optimized Software Library 論文原圖)
要將一個4個位元組的數據插入RoaringBitMap,首先要用數據的高16位,找到對應的Container,然後用數據的低16在Container中插入。
在每個Container內部,RoaringBitMap不是簡單的用BitMap來進行數據的存儲,而是把Container的類型劃分為幾種,不同的Container用來存儲不同情況的數據。
當2個位元組(4個位元組的原數據,低16位用來插入具體的Container中)的數據,總的個數小於4096個的時候,當前Container使用 array Container。為什麼是4096個呢?4096*2B=8Kb,而一個Container如果是bitmap的結構的話,最多也就是2^16bit=8Kb的空間。所以這里當數據個數小於4096使用array Container會更節省空間。當然這里名字為array Container,實際上是鏈表結構,不需要最開始就初始化4096個short int的數組。
當array Container存儲的數到4096個的時候(也就是使用內存到8Kb的時候),array Container會轉換為bitmap container,bitmap container就是一個2^16 bit普通的bitmap,可以存儲2^16 = 65536個數據。這個8Kb還有一個好處,是可以放到L1 Cache中,加快計算。
這個嚴格的說,只是一種數據壓縮存儲方法的實現。其壓縮原理是對於連續的數字只記錄初始數字以及連續的長度,比如有一串數字 12,13,14,15,16 那麼經過壓縮後便只剩下12,5。從壓縮原理我們也可以看出,這種演算法對於數據的緊湊程度非常敏感,連續程度越高壓縮率也越高。當然也可以實現其他的壓縮方法。
RoaringBitMap其核心就在於加了一層索引,利用復雜的數據結構換取了空間上的效率。需要注意的是這里並沒有增加計算的復雜度,其出色的數據結構讓其在做交並計算的時候性能也毫不遜色。
ClickHouse中有bloom_filter類型的Skipping indexs,可以方便的用來過濾數據。
ClickHouse實現了大量的BitMap的函數,用來操作BitMap。ClickHouse中的BitMap在32位的時候用的是Set實現的,大於32位的時候也是使用RoaringBitMap實現的。我們這里不看具體的函數,我們來看一個典型的使用場景。
最常見的一個場景是根據標簽來進行用戶的圈選。常見的解決辦法是有一張用戶標簽表,比如
要查詢標簽tag1='xx'和tag2='xx'的用戶需要執行SQL:
但是由於不可能對每個tag列構建一級索引,所以這條SQL執行的效率並不高。可選的一種方式是先構建關於標簽的BitMap數據結果,然後進行查詢:
(1) 創建tag的bitmap表:
(2)寫入數據
(3)查詢
如果有多張tag表,進行交並計算(要比普通的用戶表進行JOIN或者IN計算要高效很多):
Ⅶ MySQL 如何存儲大數據
行格式為Compact是如何存儲大數據的:
[vb]view plain
mysql>selectversion();
+-----------+
|version()|
+-----------+
|5.1.73|
+-----------+
1rowinset(0.01sec)
mysql>showtablestatuslike'row'G;
***************************1.row***************************
Name:row
Engine:InnoDB
Version:10
Row_format:Compact
Rows:1
Avg_row_length:81920
Data_length:81920
Max_data_length:0
Index_length:0
Data_free:0
Auto_increment:NULL
Create_time:2017-01-0421:46:02
Update_time:NULL
Check_time:NULL
Collation:latin1_swedish_ci
Checksum:NULL
Create_options:
Comment:
1rowinset(0.00sec)
我們建立一張測試表,插入數據:
[html]view plain
CREATETABLE`row`(
`content`varchar(65532)NOTNULLDEFAULT''
)ENGINE=InnoDBDEFAULTCHARSET=latin1
mysql>insertintorow(content)selectrepeat('a',65532);
QueryOK,1rowaffected(0.03sec)
Records:1Duplicates:0Warnings:0
我們使用 py_innodb_page_info.py 工具來查看錶中的頁分布:
[vb]view plain
[root@localhostmysql]#pythonpy_innodb_page_info.py-vcom/row.ibd
pageoffset00000000,pagetype<FileSpaceHeader>
pageoffset00000001,pagetype<InsertBufferBitmap>
pageoffset00000002,pagetype<FileSegmentinode>
pageoffset00000003,pagetype<B-treeNode>,pagelevel<0000>
pageoffset00000004,pagetype<UncompressedBLOBPage>
pageoffset00000005,pagetype<UncompressedBLOBPage>
pageoffset00000006,pagetype<UncompressedBLOBPage>
pageoffset00000007,pagetype<UncompressedBLOBPage>
Totalnumberofpage:8:
InsertBufferBitmap:1
UncompressedBLOBPage:4
FileSpaceHeader:1
B-treeNode:1
FileSegmentinode:1
可以看出,第4頁的 <B-tree Node>, page level <0000> 格式為數據頁,存放著MySQL的行數據。 <Uncompressed BLOB Page> 可以理解為MySQL存放大數據的地方,暫且叫作外部存儲頁。Compact格式沒有將大數據全部放在數據頁中,而是將一部分數據放在了外部存儲頁中。那麼,是全部數據在外部存儲頁中,還是一部分數據。假如是一部分數據,這一部分是多少呢?
我們使用 hexmp -Cv row.ibd 查看一下數據頁 <B-tree Node>, page level <0000> ,也就是第4頁:
[vb]view plain
|.%.W....????????|
|......:?E?......|
|.........?......|
|................|
|................|
|...?.........2..|
|...infimum......|
|supremum.?...??.|
|...............-|
|..aaaaaaaaaaaaaa|
|aaaaaaaaaaaaaaaa|
|aaaaaaaaaaaaaaaa|
|aaaaaaaaaaaaaaaa|
....
....
|aaaaaaaaaaaaaaaa|
|aaaaaaaaaaaaaaaa|
|aa...........&..|
|....??..........|
|................|
|................|
|................|
...
...
|................|
|................|
|................|
|.....p.c.?l+..:?|
Ⅷ 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.分布式處理 maprece
適用范圍:數據量大,但是數據種類小可以放入內存
基本原理及要點:將數據交給不同的機器去處理,數據劃分,結果歸約。
擴展:
問題實例:
1).The canonical example application of MapRece 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 rece(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 Rece, 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-rece過程,首先可以根據數據值或者把數據hash(md5)後的值,將數據按照范圍劃分到不同的機子,最好可以讓數據劃分後可以一次讀入內存,這樣不同的機子負責處理各種的數值范圍,實際上就是map。得到結果後,各個機子只需拿出各自的出現次數最多的前N個數據,然後匯總,選出所有的數據中出現次數最多的前N個數據,這實際上就是rece過程。
實際上可能想直接將數據均分到不同的機子上進行處理,這樣是無法得到正確的解的。因為一個數據可能被均分到不同的機子上,而另一個則可能完全聚集到一個機子上,同時還可能存在具有相同數目的數據。比如我們要找出現次數最多的前100個,我們將1000萬的數據分布到10台機器上,找到每台出現次數最多的前 100個,歸並之後這樣不能保證找到真正的第100個,因為比如出現次數最多的第100個可能有1萬個,但是它被分到了10台機子,這樣在每台上只有1千個,假設這些機子排名在1000個之前的那些都是單獨分布在一台機子上的,比如有1001個,這樣本來具有1萬個的這個就會被淘汰,即使我們讓每台機子選出出現次數最多的1000個再歸並,仍然會出錯,因為可能存在大量個數為1001個的發生聚集。因此不能將數據隨便均分到不同機子上,而是要根據hash 後的值將它們映射到不同的機子上處理,讓不同的機器處理一個數值范圍。
而外排序的方法會消耗大量的IO,效率不會很高。而上面的分布式方法,也可以用於單機版本,也就是將總的數據根據值的范圍,劃分成多個不同的子文件,然後逐個處理。處理完畢之後再對這些單詞的及其出現頻率進行一個歸並。實際上就可以利用一個外排序的歸並過程。
另外還可以考慮近似計算,也就是我們可以通過結合自然語言屬性,只將那些真正實際中出現最多的那些詞作為一個字典,使得這個規模可以放入內存。
Ⅸ android intent跳轉怎樣傳輸大數據
在Activity或者組件之前傳遞信息時,一般採用intent綁定bundle的方式傳值,但在使用過程中需要注意的是不要用bundle傳遞大容量數據:
在做項目的過程中,需要將聽寫界面的聽寫結果信息傳遞到聽寫記錄界面供顯示用,但是由於傳遞的數據量過大導致程序ANR,甚至直接報異常(傳遞的信息裡面有bitmap轉換成的byte數組、每一個片語的拼音、詞語、語音信息),經過分析發現是由於bundle不能傳遞大容量的數據信息,在stackoverflow裡面查閱發現有同行遇到類似的問題:
(1)「The size limit of Intent is still pretty low in Jelly Bean, which is somewhat lower than 1MB (around 90K), so you should always be cautious about your data length, even if your application targets only latest Android versions.」
(2)「As per my experience (sometime ago), you are able to put up to 1MB of data in a Bundleencapsulated inside Intent. I think, this restriction was valid up till Froyo or GingerBread.」
所以在通過bundle傳遞數據時只能傳遞較小的數據信息,對於在不同組件之間需要傳遞大容量數據的情況時,有幾種替代方式可以解決不能用bundle傳遞這些數據的問題:
方法一:將需要傳遞的數據寫在臨時文件或者資料庫中,再跳轉到另外一個組件的時候再去讀取這些數據信息,這種處理方式會由於讀寫文件較為耗時導致程序運行效率較低;
方法二:將需要傳遞的數據信息封裝在一個靜態的類中(注意當前組件和要跳轉到的組件必須屬於同一個進程,因為進程之間才能夠共享數據),在當前組件中為類設置內容,然後再跳轉到的組件中去取,這種處理方式效率很高,但是會破壞程序的獨立性。
具體採用哪種替代方式取決於具體的情況,本人建議採取第二種處理方式,因為這樣會大大提高程序的運行效率,至於程序的獨立性,看你怎麼去封裝這個類了。
Ⅹ 如何進行java海量數據處理,下面一段是我摘抄的問題及處理方法
lz沒理解第二步「分而治之」的思想,分治演算法是將一個大問題分解為一系列與大問題性質相同的子問題,所以在分治時不可能把相同的ip分配到不同的文件中,就像你所說的,「按照IP地址的Hash(IP)%1024值,把海量IP日誌分別存儲到1024個小文件中」,通過hash,兩個相同的ip肯定放到同一個文件中了哈