Thread Hilfe für Regex (21 answers)
Opened by lousek at 2011-08-06 17:24

topeg
 2011-08-10 14:56
#151477 #151477
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
2011-08-10T08:43:50 lousek
Bezüglich den unnötigen SQL-Abfragen:
Eigentlich mache ich ja ein "genereller" SELECT (für die rep_dirs), dann pro rep_dir ein SELECT und dann für jedes neues Verzeichnis ein INSERT, für ein aktualisiertes ein UPDATE und für ein gelöschtes ein DELETE.

Zuerst holst du alle Einträge aus der DB und vergleichst sie mit den vorhanden Dateien dann gehst du alle Differenzen durch und fügst/änderst/löschst jede Datei einzeln.

2011-08-10T08:43:50 lousek
Sehe ich das richtig, dass du sämtliche "direkte" Datenbankenfunktionen (sprich queries) als Referenzen(?) im Hash $sth_lst gespeichert hast?
Warum genau hast du z.B. den prepare im delete_old und nicht einfach im sub delete_old_files "gespeichert"?

$dbh->prepare präpariert einen Datenbankabfrage. Sie wird analysiert bereinigt und an die DB gesendet. Das kostet zeit. Es ist bei vielen gleichen Aufrufen günstiger diese einmal zu erzeugen und dann immer wieder zu verwenden. Das ich es hier direkt am Anfang des Scripts gemacht habe liegt daran, dass ich kein Objekt benutzt habe um sie unterzubringen. Ich habe eine "Vorstufe" zu einem Objekt benutzt einen Hash, den ich an jede Funktion weiterreiche. Es fehlt nur noch ein kleiner Schritt um sämtliche Datenbankaktionen in einer Klasse zu bündeln und zu abstrahieren. Da du das sicher noch nicht kennst, hätte es dich noch mehr verwirrt, als es jetzt schon der Fall ist. :-)

2011-08-10T08:43:50 lousek
- Die Funktion rel2abs konvertiert relative in absolute Pfade, aber $File::Find::Name würde ja schon den absoluten Pfad enthalten ... ?

Da kann man sich nicht immer sicher sein. Die Pfadangaben in rep_dirs können auch relativ sein. Dann gibt File::Find::find eine relative Angabe zurück. Darum schicke ich das nochmal durch File::Spec->rel2abs

2011-08-10T08:43:50 lousek
- Es wird mit return 0 unless (-f $path) erneut überprüft, ob die Datei existiert. Aber das wurde ja bereits vor dem Aufruf von process_file erledigt (return unless -f) ... ?

Zwischen den beiden Überprüfungen ist etwas zeit vergangen (nicht viel aber ein wenig.) Zudem weiß ich ja nicht wie die Funktion aufgerufen irgendwann mal aufgerufen wird. Es ist eine reine Sicherheitsmaßnahme. Man darf ruhig ein wenig zu vorsichtig. Als ich mit Perl Anfing hätte ich die Überprüfung auch nicht gemacht, doch mit der Zeit lernt man dann so etwas das Programm robust macht. :-)

2011-08-10T08:43:50 lousek
Anschliessend wird überprüft ob der Pfad bereits in der DB steht. Aber wird hier nicht für jeden einzelnen Pfad einen eigenen SELECT gemacht?
Dies wäre doch eben wieder nicht gerade so effizient ... ?
Wenn der Pfad in der DB steht (defined($id)), so wird er aktualisiert wenn die atime, mtime, ctime, oder inode nicht übereinstimmt, ansonsten wird nur der status aktualisiert.
Wenn der Pfad nicht in der DB steht, wird er "logischerweise" einfach eingefügt.

Das stimmt, es werden alle Dateien geprüft. Du holst aber auch jeden Datensatz aus der DB nur alle auf einmal. Durch das einmalige Vorbereiten der Abfrage ist das nicht aufwändiger als bei dir.
Das aufwändigste neben dem erzeugen des "Query-Handles" bei einer Abfrage ist das die Daten aus der DB in das Script geschaufelt werden müssen oder zurück. Das ist bei dir und mir identisch. Doch du hältst zudem alle Datensätze im Perlscript, was ich vermeide.

2011-08-10T08:43:50 lousek
Der letzte Teil ist wieder klar:
Alle Einträge in der DB, welche verwaist sind (status = 0), werden gelöscht.

Man könnte das ganze noch einfach erweitern, indem man geänderten Einträgen z.B den wert 3 zuweist und das später abfragt, damit bekommt man als dritten Wert alle geänderten Einträge. Dies lässt sich auch auf weitere Aktionen ausweiten.

2011-08-10T08:43:50 lousek
Bei mir werden doch viel weniger SQL-Queries benötigt?

Insgesamt hast du sieben verschiedene Queries die du jedes mal neu initialisierst. Ich habe acht Queries, die ich einmal initialisiere.
Aber du hast recht, meine erste Aussage diesbezüglich war nicht korrekt. Insgesamt machst du weniger Datenbankabfragen. Jedoch initialisierst du sie jedes mal neu, was etwas Zeit kostet.
Zusammenfassend kann man sagen, du kopierst die komplette DB nach Perl und verarbeitest sie dort, ich mache so viel wie möglich in der DB. Was einen vorteil bringt kann nur ein direkter Vergleich zeigen. Aus meiner Erfahrung kann ich aber sagen, dass Datenbankaktionen, um einiges schneller sind als vergleichbare Aktionen in Perl. Der Rest ist Geschmackssache.

Übrigens kann man eine Abfrage bei mir noch etwas beschleunigen indem man dem Query in $sth_lst{select_iamci_by_path} noch ein LIMIT 1 anhängt. Das verhindert unnötiges weiter suchen. Je nach Anzahl der Einträge ist das deutlich spürbar.

2011-08-10T08:43:50 lousek
Oder kann es sein, dass ich (trotz nachschauen auf CPAN) das mit dem begin_working() und commit() nicht ganz verstanden habe? :)

Wenn AutoCommit aktiv ist, wird nach jeder Datenbank Aktion der aktuelle Zustand für alle anderen möglichen Nutzer zur Verfügung gestellt. das kostet immer etwas Zeit und kann auch für eine Inkonsistente DB sorgen. Wenn man nun mit begin_working und commit arbeitet man das dazwischen. Das beschleunigt die Aktionen ein wenig, da keine unnötigen Aufräumarbeiten gemacht werden. Alles andere ist erst mal nicht so wichtig, da nur ein Skript gleichzeitig läuft. Willst du auch verhindern das mehrere Scripte gleichzeitig eine Tabelle nutzen musst du sie für das eine Script Exklusiv sperren.

Ich will es nochmal zusammenfassen.
Für kleine Datenmengen sind beide Scripte gleich gut, denn es macht einen Unterschied ob 10% weniger Speicher belegt werden, oder ob eine Abfrage 10% schneller ist. Wenn die Anzahl der Einträge steigt werden diese Werte immer relevanter, da es einen unterschied macht ob ein Script 500 Sekunden für 500.000 Einträge braucht oder 50 Sekunden. Auch macht es einen unterschied beim Speicherverbrauch.
Außerdem sollte man es sich immer zweimal überlegen, ob man großen Datenmengen dupliziert, und getrennt bearbeitet, denn eine spätere Synchronisation kann problematisch werden.

View full thread Hilfe für Regex