Quantcast
Channel: 黑暗執行緒
Viewing all articles
Browse latest Browse all 2311

超過一百萬個檔案的 NTFS 資料夾…

$
0
0

在 NTFS 資料夾放入超過一百萬個檔案,會發生什麼事?讀寫檔案會因此變慢嗎?Windows 會不會因此崩潰?

相信很少人有類似經驗,也不會大費周章搞個 Lab 試玩,既然幸運親身體驗過,分享一下經驗。

先說結論:在 NTFS 資料夾放超過一百萬個檔案基本上是可行的(這次遇到的案例超過 150 萬個檔案),若已知完整檔案名稱,讀、寫檔案速度不受檔案數目影響,但會影響檔案總管及部分檔案操作。

我們有個批次轉檔程式會由資料庫讀取資料、存檔後上傳 FTP,每天產生的檔案數約一千筆。因追查問題有時需要檔案內容佐證(跨系統吵架,手握呈堂證供氣勢立刻翻倍呀,你懂的),故需保留檔案。每次調查問題,多半會由資料庫查到檔案名再開 DOS 視窗「notepad 檔名」調閱檔案,用起來很順手方便,感受不到速度延遲,因此大家就忽略了資料夾檔案數每天持續成長,沒人想到要安排定期歸檔搬移排程,就這麼過了七年…

依據 TechNet 文件:NTFS 每個 Volume 的檔案數上限是 4G-1,40 億個檔案放在同一個資料夾理論上是可行的。資料夾使用 B-Tree 結構管理資料,故在已知檔名的前題下,存取檔案的速度不太受同資料夾檔案數多寡影響。資料庫索引也常用 B-Tree 結構儲存索引資料,若已知完整 Key 值,讀取速度不會因為資料筆數倍增明顯下降,也是同樣道理。

關於資料夾可容許的最大檔案數,我沒有找到明確數字。但上述文件提到一個數字(在 Maximum Sizes on an NTFS Volume 段落),如果要在一個資料夾擺放超過 30 萬個檔案,建議停用 8.3 短檔名(尤其是檔名前六碼重複機率很高時),主要是 Windows 會耗費可觀成本避免短檔名重複,推測這只發生在新増或更名時,但是「30 萬」這個數字倒也意味著單一資料夾放幾十萬個檔案仍在 NTFS 設計的容許範圍。

存取檔案速度 OK,問題會出在需要列舉或掃瞄資料夾所有檔案的情境。例如:當資料夾檔案數愈來愈多,就很難再用檔案總管開啟資料夾,一開啟就卡住,甚至導致桌面凍結,只能改用 DOS 視窗,使用 TYPE、COPY 指令存取指定檔名。而且用到 DIR xxxx_*.txt 等篩選條件也會等到地老天荒。這是簡單的數學問題,假設檔案名稱有 32 個字元,100 萬筆檔案清單,光檔名就有 32MB,除了檔名外還有日期時間檔案大小等資料,搜尋時得一一檢查權限,都會消耗記憶體、CPU 並涉及可觀的磁碟 IO 動作。而檔案數一多,系統需串接更多磁區才擺得下目錄資料,列舉檔案清單需由多個零散磁區彙整資料,也會耗費額外的讀取時間。

回到實務案例,雖然已知檔名時讀寫沒什麼感覺,但系統人員發現一些使用上的問題:

  • 檔案總管一打開內有百萬筆檔案的資料夾便卡死沒反應,還無法取消或關閉。到最後,「千萬不要點開 XXX 資料夾(很可怕,不要問)」列為系統管理員口耳相傳的交接事項。
  • DIR 可以執行列出檔案,但只見檔案清單無窮無盡捲個不停,捲到此恨綿綿無絕期,超越常人的耐心極限,檔案總數與大小始終是謎。
  • 單純 DIR 還可以看到檔名狂跑,但 DIR /OD(依日期排序)、DIR *_Blah.txt (篩選檔名特徵)則是一執行就沒反應,直到天荒地老…
  • 想用 .NET Directory.GetFiles()逐一抓取檔案歸檔,GetFiles() 會一次讀入完整清單,結果…

最後,我寫了支 .NET 歸檔程式,將檔案依日期放在 X:\Archive\yyyy\MM\dd\ 目錄下,而歸檔程式的一項挑戰是不能用 Diretory.GetFiles(),需改用 Directory.EnumerateFiles(),傳回 IEnumerable<string>,每次只取一筆,愚公移山奮戰數小時,將舊檔依日期分類,總算馴服這匹脫韁之馬。

後記,查資料在 Stackoverflow 看到一個資料夾放了 1,400 萬個檔案的案例,結論是 NTFS 資料夾能容納的檔案數比想像多很多,但在這種極端情境下要留意其副作用。


Viewing all articles
Browse latest Browse all 2311

Trending Articles