今天在想這個問題,乙個目錄下有太多(20萬)個以md5串作為檔名的檔案,想把他們按相同的字首放到子目錄中,假如字首的長度是1個字母,就只需要建立16(6個字母+10個數字)個父目錄,但是這能保證每個目錄下的檔案個數大致相當嗎,md5串的各個字母的分布是不是等概率的呢,考慮這樣幾個md5串:
cfcd208495d565ef66e7dff9f98764dac4ca4238a0b923820dcc509a6f75849b
c81e728d9d4c2f636f067f89cc14862c
eccbc87e4b5ce2fe28308fd9f2a7baf3
a87ff679a2f3e71d9181a67b7542122c
e4da3b7fbbce2345d7772b0674a318d5
1679091c5a880faf6fb5e6087eb1b2dc
8f14e45fceea167a5a36dedd4bea2543
c9f0f895fb98ab9159f51fd0297e236d
45c48cce2e2d7fbdea1afc51c7c6ad26
是選第乙個字母作為目錄好還是選最後乙個字母好呢(或者是選中間的其他字母),為了解決這個問題,我大致計算了一下md5串各個位上字母的熵,程式如下(**中的libjade是我的python實用工具庫 ):
#coding:utf8from libjade import *
from math import log
def entropy(lst):
st=set(lst)
ps={}
l=len(lst)
for i in st:
ps[i]=float(lst.count(i)) / l
return sum([-p * log(p, 2) for p in ps.values()])
if __name__=='__main__':
lsts={}
for i in range(300000):
s=md5(str(i))
for j in range(0, 32):
if not j in lsts:
lsts[j]=[s[j]]
else:
for j in range(0, 32):
print j, entropy(lsts[j])
執行結果顯示,熵幾乎都是4,說明每個位置的字母都大概是均勻分布的:
0 3.99994452191 3.9999799341
2 3.99997465219
3 3.99992966376
4 3.99997557506
5 3.99997854535
6 3.99995146435
7 3.9999726059
8 3.99996545565
9 3.9999705381
10 3.99996871359
11 3.99995660577
12 3.99995196213
13 3.99995732855
14 3.99994707575
15 3.99995717605
16 3.99995565124
17 3.99996349489
18 3.99997235641
19 3.99997430926
20 3.99996398965
21 3.99994457348
22 3.9999782949
23 3.99998414043
24 3.9999664288
25 3.99994949642
26 3.99994869626
27 3.99997557227
28 3.99997027123
29 3.99993962184
30 3.99993844981
31 3.99995679387
當md5串足夠多的時候,隨便選哪個字母作為目錄都能大致均勻的將檔案雜湊到各個目錄中。但是考慮到作業系統在乙個目錄中查詢檔案時,也是在一棵由檔名構成的類似b+樹的資料結構中查詢目標檔名,我們知道字串匹配時從左到右進行的,如果乙個目錄中的檔名字首都想同,那麼在b+樹種查詢時,從根節點到目標節點之間途徑的每個節點每至少比較完字首部分才能確定兩個字串不同,這樣就做了大量的無用比較,而相反的,如果乙個目錄中的檔名僅僅是字尾相同, 那麼比較前面的部分就可以快速區分檔名是否不同,相同的字尾僅僅會在b+樹中找到目標節點時比較一次,這樣就節省了大量的無用的比較次數。
因此得出結論,雖然md5串中各個字母都是分布均勻的,但是盡量使用後面的字母作為目錄名進行大量檔案的雜湊會更好一些。
如果檔案數量太多,使用最後乙個字母進行雜湊僅僅只能保證每個目錄中的平均檔案數是原來總數的16分之一。使用更多的字母來雜湊可以繼續按照每個字母16倍的速度縮小每個目錄下雜湊的檔案數。如果使用2個字母,將產生256個資料夾,3個字母4096個,4個字母65536個,個人感覺最多使用3個字母做同級目錄是比較合適的。如果3個字母雜湊後每個字目錄中檔案還是太多,則可以繼續進行雜湊。各種情況典型的目錄結構如:
da/cfcd208495d565ef66e7dff9f98764dada/c4ca4238a0b923820dcc509a6f7583da
da/64/cfcd208495d565ef66e7dff9f98764da
da/64/c4ca4238a0b923820dcc509a6f7564da
da/64/7/cfcd208495d565ef66e7dff9f98764da
da/64/7/c4ca4238a0b923820dcc509a6f7764da
da/64/87/cfcd208495d565ef66e7dff9f98764da
da/64/87/c4ca4238a0b923820dcc509a6f8764da
posted on 五月 29, 2012 at 8:46 上午
MD5的簡單學習,鑰匙串
c語言中的md5,寫法主要是 1.建立md5摘要 2.初始化摘要 3.更新md5的摘要 4,結束md5 oc中的md5,略有不同.鑰匙串部分 鑰匙串實在mac os8.7 ios7之後被加入的 鑰匙串可以包含多種資料資訊,密碼 私鑰 電子證書 加密筆記 它是基於硬體的,將資料儲存在加密晶元中 存放在...
shell中計算字串的md5值
echo 123 md5sum ba1f2511fc30423bdbb183fe33f3dd0f php r echo md5 123 202cb962ac59075b964b07152d234b70 兩者的md5值不一致,於是有很多有趣的解法 1 mysql解法 mysql select md5 ...
shell下取得字串的md5值
今日群裡問起乙個問題 echo 123 md5sum ba1f2511fc30423bdbb183fe33f3dd0f php r echo md5 123 202cb962ac59075b964b07152d234b70 兩者的md5值不一致,於是有很多有趣的解法 1 mysql解法 mysql ...