2012-05-21 7 views
8

Ich habe eine externe Festplatte mit einer Milliarde Dateien. Wenn ich die externe Festplatte in Computer A einbinde, durchsucht mein Programm den Pfad aller Dateien und speichert den Pfad der Dateien in einer Datenbanktabelle. Wenn ich dann die externe Festplatte austausche, bleiben diese Daten in der Tabelle. Das Problem ist, wenn einige Dateien auf dem Computer B gelöscht werden, und ich es erneut auf dem Computer A mount, muss ich die Datenbanktabelle in Computer A synchronisieren. Ich möchte jedoch nicht alle Dateien erneut scannen, weil es dauert viel Zeit und viel Zeit verschwenden. Gibt es eine Möglichkeit, die Datenbanktabelle zu aktualisieren, ohne alle Dateien zu durchsuchen und gleichzeitig den verwendeten Speicher zu minimieren?Handle eine große Anzahl von Dateien

Außerdem ist in meinem Fall Gedächtnis Begrenzung wichtiger als Zeit. Das bedeutet, dass ich mehr Speicher sparen möchte, als mehr Zeit zu sparen.

Ich denke, ich kann die Dateien in viele Abschnitte schneiden und eine bestimmte Funktion (möglicherweise SHA1?) Verwenden, um zu überprüfen, ob die Dateien in diesem Abschnitt gelöscht werden. Ich kann jedoch keine Möglichkeit finden, die Dateien in die Abschnitte zu schneiden. Kann mir jemand helfen oder mir bessere Ideen geben?

+0

Löschen wie in: Ein systembasiertes Löschen, das Sie nicht kontrollieren können? oder Ein Löschen, das von einer Anwendung ausgelöst wird, in der Sie etwas tun können? – Krrose27

+0

Warum benötigt der Scanvorgang viel Speicherplatz? Sie listen die Dateien im Grunde nur in einem Verzeichnis auf, oder? – Joni

+0

Ja, jedoch kann ich nicht steuern, wie viele Dateien in einem Verzeichnis gespeichert sind. Ein Verzeichnis kann 1 Milliarde Dateien enthalten. Außerdem, wenn ich beim Scannen einer Datei sofort eine Daten einfüge, spart es viel Speicher, ist aber wegen der I/O-Probleme sehr zeitaufwendig. Wenn ich den Masseneinsatz verwende, ist es effizienter. – s011208

Antwort

0

Theoretisch könnten Sie Dinge beschleunigen, indem Sie "modifizierte" Zeitstempel in Verzeichnissen überprüfen. Wenn ein Verzeichnis nicht geändert wurde, müssen Sie keine Dateien in diesem Verzeichnis überprüfen. Leider müssen Sie mögliche Unterverzeichnisse durchsuchen, und um sie zu finden, müssen Sie das Verzeichnis scannen ... es sei denn, Sie haben die Verzeichnisbaumstruktur gespeichert.

Und natürlich, das ist egal, Sie haben ein flaches Verzeichnis mit einer Milliarde Dateien.

Ich stelle mir vor, dass Sie alle Dateipfade im Speicher zusammenstellen, damit Sie sie sortieren können, bevor Sie die Datenbank abfragen. (Und das Sortieren ist eine gute Idee ...) Es gibt jedoch eine Alternative zum Sortieren im Speicher:

  1. Schreiben Sie die Dateipfade in eine Datei.
  2. Verwenden Sie ein externes Dienstprogramm zum Sortieren, um die Datei in die Reihenfolge der Primärschlüssel zu sortieren.
  3. Lesen Sie die sortierte Datei und führen Sie Batch-Abfragen für die Datenbank in Schlüsselreihenfolge durch.

(Haben Sie wirklich eine Milliarde Dateien auf einer Disc haben? Das klingt wie ein schlechtes Design für Ihre Datenspeicher ...)

+0

Ich werde nie eine Milliarde Dateien in eine externe Festplatte stecken, es ist wirklich ein Desaster; Ich kann jedoch nicht versprechen, dass alle Benutzer dies nicht tun werden. – s011208

+0

@ s011208 - Nun, ich würde geneigt sein, den Benutzern zu sagen, dass es ihre Schuld ist, wenn Ihr System eine lange Zeit braucht, wenn sie eine lächerliche Anzahl von Dateien auf die Disc legen. –

1

Wenn Sie keine Kontrolle über das Dateisystem Auf der Festplatte haben Sie keine andere Wahl, als die Dateinamen auf der gesamten Festplatte zu scannen. Zur Liste der Dateien, die gelöscht wurden Sie so etwas tun könnte:

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 

Eine Lösung für das db Performance-Problem könnte die Dateinamen in eine Liste von irgendeiner Art ansammeln und machen Sie einen Bulk-Insert/Update, wenn Sie erreichen Sie 1000 Dateien.

Wie für Verzeichnisse mit 1 Milliarde Dateien müssen Sie nur den Code ersetzen, der die Dateien mit etwas auflistet, das die C-Funktionen opendir und readdir umschließt. Wenn ich es wäre, würdest du dir im Moment keine Sorgen machen. Keine vernünftige Person hat 1 Milliarde Dateien in einem Verzeichnis, weil solche Dinge Dateisysteme und gängige Betriebssystem-Tools lahm legen, so dass das Risiko gering ist und die Lösung einfach ist.

+0

Ihre Lösung ist, was Android-System wirklich tun! Der Nachteil dieser Lösung besteht jedoch darin, dass Sie das Attribut der Datei im Speicher ablegen müssen, z. B. map. Allerdings hat Android die Speicherbeschränkung! Wenn Sie nur 10 tausend Dateien haben, ist es in Ordnung. Wenn Sie mehr als hunderttausend Dateien haben, wird das Programm gezwungen, zu beenden. Nun möchte ich, genau wie bei meiner Frage, eine Möglichkeit finden, alle Dateien auf der Festplatte in Abschnitte zu schneiden, so dass ich gleichzeitig Abschnitte erstellen und das Problem der Speicherbegrenzung vermeiden kann! – s011208

+1

Warum sollten die Attribute der Dateien im RAM gespeichert werden, dafür ist die Datenbank gedacht? Oder meinst du die temporäre Liste, die für den Masseneinsatz verwendet wird? Sie können die Bulk-Größe basierend auf dem verfügbaren Speicher dynamisch auswählen, anstatt eine feste Größe zu verwenden ... – Joni

0

Haben Sie eine Liste, was gelöscht wird, wenn das Löschen stattfindet (oder ändern Sie den Prozess, der gelöscht wird, um dies zu erstellen)?Wenn das nicht der Fall ist, können Sie eine Liste von "Ich wurden gelöscht" mit einem Zeitstempel erstellen und dann Elemente aus dieser Liste auswählen, um nur nach Änderungen zu synchronisieren. Natürlich möchten Sie immer noch eine Art Batch-Job haben, um während einer langsamen Zeit auf dem Server zu synchronisieren, aber ich denke, das könnte die Last reduzieren.

Eine andere Option kann sein, je nachdem, was den Code ändert, dass der Prozess die Datenbanken (wenn Sie mehrere Knoten haben) einfach beim Löschen aktualisiert. Dies würde eine gewisse Kopplung in die Systeme einführen, wäre aber die effizienteste Art, dies zu tun.

Die besten Möglichkeiten meiner Meinung nach sind einige Variationen über die Idee von Messaging, dass ein Löschen aufgetreten ist (auch wenn das nur eine Datei ist, die Sie an einige wo mit einer Liste kürzlich gelöschter Dateien schreiben), oder irgendeine Art von direkt Callback-Mechanismus, entweder durch Code oder nur durch Anpassen des persistenten Datenspeichers, den die Anwendung direkt aus dem Löschprozess verwendet.

Selbst wenn all dies gesagt wurde, müssten Sie immer eine Art Index-Synchronisation oder periodische Plausibilitätsprüfung der Indizes durchführen, um sicher zu sein, dass alles korrekt abgeglichen ist.

Sie könnten (und ich wäre schockiert, wenn Sie nicht basierend auf der Anzahl der Dateien, die Sie haben) den Dateibereich in Ordner mit sagen wir 5.000 bis 10.000 Dateien pro Ordner partitionieren und dann erstellen eine einfache Datei mit einem Hash der Namen aller Dateien im Ordner. Dies würde Löschungen fangen, aber ich denke immer noch, dass ein direkter Rückruf einer Form, wenn das Löschen auftritt, eine viel bessere Idee ist. Wenn Sie einen monolithischen Ordner mit all diesen Dingen haben, erstellen Sie etwas, um das in separate Ordner zu zerlegen (wir benutzten eine einfache Nummer unter dem Hauptordner, damit wir ad nauseum weitermachen konnten) sollte alles sehr beschleunigen; Selbst wenn Sie dies für alle neuen Dateien tun müssen und die alten Dateien so belassen, wie sie sind, könnten Sie zumindest das bluten beim Dateiabruf stoppen.

Meiner Meinung nach, da Sie einen Index der Dateien programmgesteuert steuern, sollten Sie das gleiche Programm irgendwie beteiligt haben (oder benachrichtigt), wenn Änderungen zum Zeitpunkt der Änderung des zugrunde liegenden Dateisystems auftreten, im Gegensatz zu zulassen Änderungen passieren und dann alles nach Updates durchsehen. Um die Ausreißer, bei denen diese Kommunikation unterbrochen wird, abzufangen, sollten Sie natürlich auch einen Synchronisationscode verwenden, um zu überprüfen, was sich im Dateisystem befindet, und den Index regelmäßig zu aktualisieren (obwohl dies möglicherweise zu der Hauptanwendung ausgelagert werden sollte)).

0

Wenn Speicher wichtig ist, würde ich für die Betriebssystem-Einrichtungen gehen.

Wenn Sie ext4 haben, nehme ich an, Sie sind auf Unix (Sie können auf anderen Betriebssystemen wie Win finden Sie zu finden). Wenn dies der Fall ist, können Sie den Befehl native find verwenden (dies wäre für die letzte Minute, Sie können sich natürlich die letzte Scanzeit merken und diese nach Belieben ändern): find/directory_path -type f -mtime -1 -print

Natürlich werden Sie die Löschungen nicht haben. Wenn ein heuristischer Algorithmus für Sie arbeitet, können Sie einen Thread erstellen, der langsam zu jeder in Ihrer Datenbank gespeicherten Datei geht (was immer zuerst angezeigt werden muss, dann von neuer zu älter) und prüfen, ob dieser noch online ist. Dies wird nicht viel Speicher verbrauchen. Ich schätze, Sie werden dem Benutzer sowieso keine Milliarden Dateien zeigen können.

Verwandte Themen