Sven Rautenberg: Array nach Werten filtern

Beitrag lesen

Moin!

Das Benutzer-Array sieht so aus:

Klarer Fall von schlechter Organisation, wie wir ja schon feststellten.

Auch wenn das Array so aus der Datenbank rauskommt, heißt das noch nicht, dass man es auch so lassen muss. Denn in der Tat suchst du dir hier einen Wolf, wenn du alle Array-Einträge einer bestimmten UID brauchst.

[2] => Array (
  [uid] => 5
  [persnr] => 45
  [persnr4] => 0045
  [nachname] => F..
  [vorname] => R..
  [anteil] => 70
  [kst] => 2400
  [sollzeit] => 100
  [lohn] => 0
  [stdsatz_soll] => 0 )

[3] => Array (
  [uid] => 5
  [persnr] => 45
  [persnr4] => 0045
  [nachname] => F..
  [vorname] => R..
  [anteil] => 30
  [kst] => 2500
  [sollzeit] => 100
  [lohn] => 0
  [stdsatz_soll] => 0 )

Wie schon von dir zutreffend festgestellt, benötigst du die UID nicht in den Daten, sondern als Index. Und wie man an den zwei Elementen oben sieht, sind sehr viele Informationen, die sich auf dieselbe UID beziehen, natürlich identisch und somit redundant. Also verzichtbar.

Deshalb mein Vorschlag zur Neuorganisation:

[UID (5)] => Array (
  [persnr] => 45
  [persnr4] => 0045
  [nachname] => F..
  [vorname] => R..
  [sollzeit] => 100
  [lohn] => 0
  [stdsatz_soll] => 0
  [verteilung] => Array(
    [0] => Array(
      [anteil] => 30
      [kst] => 2500)
    [1] => Array(
      [anteil] => 70
      [kst] => 2400)
    )
 )

So wäre ein vernünftig aufgebautes Array für die Aufgabe nutzbar. Du kriegst direkten Zugriff via UID auf alle Personalstammdaten, und der Subindex "Verteilung" enthält ein Array mit allen Details zur Aufteilung auf die jeweiligen Kostenstellen. Ich habe dabei angenommen, dass "Lohn" und "Stdsatz_Soll" Bestandteil der Personalstammdaten sind, wenn die zur Kostenstellenaufteilung gehören, müssen die natürlich jeweils mit ins Array hinein.

So ein Array lässt sich beim Auslesen der entsprechenden DB-Abfrage mit ein wenig Umkopieren der abgefragten Daten relativ problemlos herstellen. Entsprechend wird dann die Schleife bei der Berechnung umgebaut.

Ich werde mal die Dauer der einzelnen Abschnitte messen. Wenn es haupsächlich am INSERT liegt, kann ich da nicht viel machen. Das Anzeigen der Daten nur aus der Zwischentabelle geht ruck-zuck, das möchte ich auch so lassen.

INSERT ist eine DB-Schreiboperation. Deren Geschwindigkeit hängt von einigen Faktoren ab, die man ebenfalls beeinflussen kann:

  • Beim Schreiben von vielen gleichartigen Daten in dieselbe Tabelle lassen sich INSERTs zusammenfassen zu einem einzigen Befehl. Der wird dann insgesamt schneller ausgeführt, als die Summe aller Einzelbefehle.

  • Wenn die Datenbank parallel in derselben Tabelle auch viel gelesen wird, wäre es eine Idee, die Storage-Engine zu checken. MyISAM sperrt zum Schreiben immer die gesamte Tabelle, InnoDB sperrt nur den jeweiligen Datensatz.

  • Das Schreiben von Indexen kostet ebenfalls zusätzliche Zeit. Zuviele Indexe sind also eher negativ, insbesondere wenn sie tatsächlich nirgendwo benötigt werden.

Es sind halt viele Schleifendurchläufe, da machen wahrscheinlich kleine Verbesserungen etwas aus.

Definitiv. Der Gewinn von einer Millisekunde pro Schleifendurchlauf sorgt bei hunderttausend Durchläufen für einen Zeitgewinn von hundert Sekunden.

Deshalb ist es innerhalb deiner Berechnungsschleife auch wichtig, dass du überflüssigen Code rauswirfst. Alle Prüfungen, die sich in jeder Schleife wiederholen, deren Ergebnis sich innerhalb der Schleife aber nicht ändern kann, sind überflüssig und gehören nach außerhalb der Schleife platziert.

Beispielsweise:

if ($user_array!=NULL) { - warum prüfst du immer und immer wieder, ob deine Benutzerdaten vorhanden sind?

$uid = $i[uid]; - Warum kopierst du Variablen? Nutze doch einfach direkt $i[uid].

Außerdem halte ich es für extrem fragwürdig, dass du vor jedem INSERT noch ein SELECT auf die Datenbank machst. Damit kriegst du wirklich jede Performance kaputt. Wenn dein Skript als Auswertungstool statistische Daten sammelt und zwischenspeichert, dann kann es die errechneten Werte auch erstmal in einem Array ablegen, und erst ganz am Ende in die Tabelle schreiben. Vorteil: Der prüfende Zugriff, ob ein Ergebnis schon existiert, kommt ohne DB-Query aus und ist tausendmal schneller.

- Sven Rautenberg