Files

文件夾中有數百萬個(小)文本文件

  • December 16, 2017

我們希望在 Linux 文件系統中儲存數百萬個文本文件,目的是能夠壓縮並將任意集合作為服務提供。我們嘗試了其他解決方案,例如鍵/值數據庫,但我們對並發性和並行性的要求使得使用本機文件系統成為最佳選擇。

最直接的方法是將所有文件儲存在一個文件夾中:

$ ls text_files/
1.txt
2.txt
3.txt

在 EXT4 文件系統上應該是可能的,它對文件夾中的文件數量沒有限制。

兩個 FS 程序將是:

  1. 從網路抓取中寫入文本文件(不受文件夾中文件數量的影響)。
  2. 壓縮選定的文件,由文件名列表給出。

我的問題是,在一個文件夾中儲存多達一千萬個文件會影響上述操作的性能或一般系統性能,這與為文件創建子文件夾樹有什麼不同嗎?

ls命令,甚至是 shell 的 TAB 補全或萬用字元擴展,通常會以字母數字順序顯示它們的結果。這需要閱讀整個目錄列表並對其進行排序。在單個目錄中有一千萬個文件,此排序操作將花費不可忽略的時間。

如果你能抵制製表符完成的衝動,例如寫下要壓縮的文件名,應該沒有問題。

萬用字元的另一個問題可能是萬用字元擴展可能會產生比最大長度命令行更多的文件名。對於大多數情況,典型的最大命令行長度綽綽有餘,但是當我們談論單個目錄中的數百萬個文件時,這不再是一個安全的假設。當萬用字元擴展中超過最大命令行長度時,大多數 shell 將簡單地使整個命令行失敗而不執行它。

這可以通過使用以下find命令執行萬用字元操作來解決:

find <directory> -name '<wildcard expression>' -exec <command> {} \+

或盡可能使用類似的語法。將find ... -exec ... \+自動考慮最大命令行長度,並根據需要多次執行命令,同時為每個命令行擬合最大數量的文件名。

這非常接近基於意見的問題/答案,但我會嘗試提供一些事實和我的意見。

  1. 如果文件夾中有大量文件,任何嘗試列舉它們的基於 shell 的操作(例如mv * /somewhere/else)都可能無法成功擴展萬用字元,或者結果可能太大而無法使用。
  2. ls列舉大量文件比列舉少量文件需要更長的時間。
  3. 文件系統將能夠處理單個目錄中的數百萬個文件,但人們可能會遇到困難。

一種建議是將文件名分成兩個、三個或四個字元塊,並將它們用作子目錄。例如,somefilename.txt可能儲存為som/efi/somefilename.txt. 如果您使用數字名稱,則從右到左而不是從左到右拆分,以便分佈更均勻。例如12345.txt可能儲存為345/12/12345.txt.

您可以使用等效項zip -j zipfile.zip path1/file1 path2/file2 ...來避免在 ZIP 文件中包含中間子目錄路徑。

如果您從網路伺服器提供這些文件(我不完全確定這是否相關),隱藏此結構以支持在 Apache2 中具有重寫規則的虛擬目錄是微不足道的。我認為 Nginx 也是如此。

引用自:https://unix.stackexchange.com/questions/411091