2012-05-21 127 views
8

我有一個具有十億個文件的外部磁盤。如果我在計算機A中安裝外部磁盤,我的程序將掃描所有文件的路徑並將文件的路徑保存在數據庫表中。之後,當我彈出外部磁盤時,這些數據仍將保留在表格中。問題是,如果某些文件在計算機B中被刪除,並且我再次將其裝載到計算機A,則必須同步計算機A中的數據庫表。但是,我不想再次掃描所有文件,因爲它需要很多時間和浪費大量的記憶。有沒有辦法在不掃描所有文件的情況下更新數據庫表,同時最大限度地減少使用的內存?處理大量文件

此外,在我的情況下,內存限制比時間更重要。這意味着我寧願節省更多的內存,也不願意節省更多的時間。

我想我可以將文件剪切成很多部分,並使用一些特定的功能(可能是SHA1?)來檢查本節中的文件是否被刪除。但是,我找不到將文件剪切到各個部分的方法。任何人都可以幫助我或給我更好的想法嗎?

+0

刪除如下:基於系統的刪除,你無法控制?或由某個應用程序觸發的刪除,您可以在其中執行某些操作? – Krrose27

+0

爲什麼掃描過程使用大量內存?你基本上只是把文件一次列在一個目錄中,對嗎? – Joni

+0

是的,但是,我無法控制目錄中有多少個文件。一個目錄可能有10億個文件。另外,如果我在立即掃描文件時插入一個數據,它會節省大量的內存,但由於I/O問題非常耗時。如果我使用批量插入,它更有效率。 – s011208

回答

0

理論上,您可以通過檢查目錄上的「已修改」時間戳來加快速度。如果一個目錄沒有被修改,那麼你不需要檢查該目錄中的任何文件。不幸的是,你需要掃描可能的子目錄,並且找到它們涉及掃描目錄......除非你保存了目錄樹結構。

當然,這是毫無意義的,你有一個包含十億個文件的平面目錄。


我想你正在裝配內存中的所有文件路徑,以便在查詢數據庫之前對它們進行排序。 (並且對它們進行排序是個好主意......)但是,在內存中有一種替代方法:

  1. 將文件路徑寫入文件。
  2. 使用外部排序實用程序將文件排序爲主鍵順序。
  3. 讀取排序文件,並按鍵順序對數據庫執行批量查詢。

(你真的有十億文件的光盤上?這聽起來像一個糟糕的設計爲您的數據存儲...)

+0

我永遠不會把十億個文件放在外部磁盤上,這真是一場災難;但是,我不能保證所有用戶都不會這麼做。 – s011208

+0

@ s011208 - 好吧,我傾向於告訴用戶,如果您的系統在光盤上放置數量可觀的文件時需要很長時間,那麼這是他們的錯。 –

1

如果你沒有在文件系統控制在磁盤上,您別無選擇,只能掃描整個磁盤上的文件名。要列出已被刪除,你可以做這樣的事情的文件:

update files in database: set "seen on this scan" to false 
for each file on disk do: 
    insert/update database, setting "seen on this scan" to true 
done 
deleted files = select from files where "seen on this scan" = false 

有解決的數據庫性能問題,可以積累的文件名到某種形式的名單,並做了批量插入/更新每當你達到1000個文件。

至於具有10億個文件的目錄,您只需要將列出文件的代碼替換爲包含C函數opendirreaddir的文件。如果我是你,現在不用擔心它太多。沒有一個理智的人在一個目錄中擁有10億個文件,因爲這樣的事情削弱了文件系統和常見的操作系統工具,所以風險很低,解決方案很簡單。

+0

你的解決方案是Android系統真正做的!但是這個解決方案的缺點是你必須將文件的屬性存儲在內存中,比如map。但是,android有內存限制!當你只有一萬個文件時,它很好。如果你有超過十萬個文件,程序將被迫完成。現在就像我的問題一樣,我想找到一種方法將磁盤中的所有文件都切分爲多個部分,以便我可以一次完成一個部分,並避免內存限制問題! – s011208

+1

爲什麼文件的屬性必須存儲在RAM中,這就是數據庫的用途,對吧?或者你的意思是用於批量插入的臨時列表?您可以根據可用內存動態選擇批量大小,而不是使用修訂大小...... – Joni

0

當刪除發生時(或更改任何進程刪除以創建此項目),您是否有刪除內容的列表?如果是這樣,你有沒有列出「我已被刪除」的時間戳,然後從這個列表中選取項目,以便只更改已更改的內容?當然,你仍然希望有某種批處理作業在服務器上慢速同步,但我認爲這可以減少負載。

根據更改代碼的情況,另一種選擇是讓該進程直接刪除時更新數據庫(如果有多個節點)。這會引入一些耦合到系統中,但會是最有效的方式。

在我看來,最好的方式是發送消息的想法發生了一些變化,即刪除已發生(即使這只是一個文件,您可以使用最近刪除的文件列表向某些位置寫入文件),或者某種直接回調機制,無論是通過代碼還是通過調整應用程序直接從刪除過程中使用的持久性數據存儲。

即使有這些說法,您總是需要對索引進行某種索引同步或定期完整性檢查,以確保所有內容都正確匹配。

如果文件夾中的文件空間分割成5000-10,000個文件夾等文件,你可以(並且我會感到震驚的,如果你不需要根據你有的文件數量),然後創建一個簡單的文件,它具有文件夾中所有文件名稱的哈希值。這將會捕獲刪除,但我仍然認爲刪除時發生的某種形式的直接回調是一個更好的主意。如果你有一個包含所有這些東西的單片文件夾,創建一些東西把它分解成單獨的文件夾(我們在主文件夾下使用了簡單的數字,這樣我們就可以繼續使用廣告)。即使您必須爲所有新文件執行此操作,並將舊文件保持原樣,至少您可以在文件檢索時停止流血。

在我看來,由於您是以編程方式控制文件的索引,所以在更改底層文件系統時發生更改時,應該確實有相同的程序參與(或通知),而不是允許發生變化,然後查看所有更新。自然地,爲了捕捉通信中斷的異常點,您還應該在那裏有同步代碼,以實際檢查文件系統中的內容並定期更新索引(儘管這可能並可能應該批量化爲主程序)。

0

如果內存很重要,我會去操作系統設施。

如果你有ext4,我會假設你在Unix上(你可以在其他操作系統上安裝find,例如Win)。如果是這種情況,您可以使用本地查找命令(這將是最後一分鐘,當然,您可以記住最後一次掃描時間並將其修改爲任何您喜歡的內容): find/directory_path -type f -mtime -1 -print

當然,你不會有刪除。如果一種啓發式算法適用於您,那麼您可以創建一個線程,緩慢地轉到存儲在數據庫中的每個文件(無論您需要先顯示,然後從較新顯示到較舊),然後檢查它是否仍處於聯機狀態。這不會消耗太多內存。我估計你無論如何都無法向用戶展示數十億個文件。