Joah.: Datenbankoptimierung

Hallo,
bräuchte mal bei meiner grundlegenden Denkweise zur Datenbankoptimierung eure Hilfe.

Ich entwickele gerade mit einem Arbeitskollegen einen Anzeigenmarkt mit insgesamt 20 verschiedenen Märkten (z.B. Automarkt, Immobilien, Telekommunikation etc.)

Hier wird ja jede Rubrik andere Merkmale haben: Autos z. B. Kilometerstand, Innenfarbe, Aussenfarbe, Metalliclackierung, Baujahr, Klimaanlage, etc.

Eine Immobilie hat u.a. wiederrum die Merkmale Baujahr, m², Garage, etc.

Wir rechnen später mit weit mehr als 100.000 Anzeigen pro Markt.

Momentan sind wir in der Überlegungsphase, wie wir die Datenbank designen sollen. Sie soll performant als auch einfach zu handeln sein.

Folgende Grundüberlegungen haben wir hinter uns:

  • entweder zu jedem Markt 2 Tabellen, eine für die Anzeigen, eine für die Merkmale. Dann hier in jeder Tabelle für eine Anzeige einen Datensatz     oder

  • zu jedem Markt 2 Tabellen, eine für die Anzeigen, eine für die Merkmale aber hier die verschiedenen Merkmale mit einem Index auf die Anzeige untereinenander in jeweils einem Datensatz    oder

  • zu jedem Markt 1 Tabelle und für JEDES merkmal eine eigene Tabelle, dieser Vorschlag wurde von einem Arbeitskollegen gemacht, viel halten tue ich davon nicht :)

Was habt ihr für Ideen? Wie könnte man die Datenbank am idealsten designen?

Danke für eure Hilfe.

Joah.

  1. bräuchte mal bei meiner grundlegenden Denkweise zur Datenbankoptimierung eure Hilfe.

    Ich entwickele gerade mit einem Arbeitskollegen einen Anzeigenmarkt mit insgesamt 20 verschiedenen Märkten (z.B. Automarkt, Immobilien, Telekommunikation etc.)

    Hier wird ja jede Rubrik andere Merkmale haben: Autos z. B. Kilometerstand, Innenfarbe, Aussenfarbe, Metalliclackierung, Baujahr, Klimaanlage, etc.

    Eine Immobilie hat u.a. wiederrum die Merkmale Baujahr, m², Garage, etc.

    Ich würd's in etwa so machen:

    Markt
    m_id, text, ...

    Markt_optionen (Merkamle)
    m_id, o_id, val_id

    Optionen (Merkmale):
    o_id, text

    optionen_werte:
    o_id, val_id, text

    So lassen sich Variabel verschiedenen Eigenschaften mit unterschiedlichen Anzahlen von Werten beschreiben.

    Struppi.

  2. Huhu Joah

    mmmmh, wie wär es denn mit vier Tabellen?

    Anzeigen
    --------
    A_ID, M_ID

    Maerkte
    -------
    M_ID,F_ID,Titel des Marktes (Hund, Katze, Maus etc.)

    Felder (Merkmale)
    -----------------
    F_ID, Titel des Merkmales (Farbe, Baujahr etc.)

    Details
    -------
    D_ID,F_ID,A_ID, Inhalt des Merkmales

    Anzeigen -> Maerkte (1->n) oder (1->1)
    Maerkte -> Felder(Merkmale) (n->n)
    Details -> Felder(Merkmale) (1->1)
    Details -> Anzeigen (n->1)

    Der eigentliche Inhalt steht dann in den Details.

    so grob jedenfalls und ohne vorher Kaffee getrunken zu haben.

    Das berücksichtigt noch nicht, dass Du ja auch noch Kunden hast.
    Also noch mindestens eine weitere Tabelle.

    Viele Grüße

    lulu

    --
    bythewaythewebsuxgoofflineandenjoytheday
    1. Der eigentliche Inhalt steht dann in den Details.

      Ja so hab ich auch schon überlegt. Dann werden aber später mehrere Millionen Datensätze in einer Tabelle stehen. das ist ja auch nicht das optimale, oder?

      1. Hi Joah

        Ja so hab ich auch schon überlegt. Dann werden aber später mehrere Millionen Datensätze in einer Tabelle stehen. das ist ja auch nicht das optimale, oder?

        Mehrere Millionen sind nicht wirklich eine grosse Belastung für eine Datenbank, wenn du vernünftig Indizes einsetzt.

        Gruss Daniela

      2. Huhu Joah

        Ja so hab ich auch schon überlegt. Dann werden aber später mehrere Millionen Datensätze in einer Tabelle stehen. das ist ja auch nicht das optimale, oder?

        Irgend eine Archivierungsstrategie braucht ihr ja in jedem Fall.
        (z.B. je Kalenderjahr eine neue Tabelle)

        Wobei ja (Klein-)Anzeigedaten relativ schnell uninteressant werden.
        Da wird man nicht viel archivieren müssen.

        Ein paar Millionen Datensätze tun aber auch nicht weh wenn das DB-Layout stimmt.
        Dafür sind die Dinger ja schliesslich da, sonst könnte man ja gleich wieder auf den guten alten Schuhkarton zurückgreifen.

        Viele Grüße

        lulu

        --
        bythewaythewebsuxgoofflineandenjoytheday
      3. Der eigentliche Inhalt steht dann in den Details.

        Ja so hab ich auch schon überlegt. Dann werden aber später mehrere Millionen Datensätze in einer Tabelle stehen. das ist ja auch nicht das optimale, oder?

        Wenn du die Merkmale nicht von den Daten trennst, wirst du 100,000ende leere Spalten haben. auch nicht so optimal.

        Struppi.

      4. Hi,

        es ist eigentlich eine natürliche Aufgabe einer "Datenbank" viele bis sehr viele Datensätze zu verwalten. Ob die in 2 Tabellen stehen oder in einer sollte imho absolut irrelevant sein.

        Deine Datenmodellierung (Grad der Normalisierung ebenso wie Wahl von Indices) sollte deinen Anwendungsfällen entsprechen. Je nach Datenbanksystem gibt es verschiedene Optimierungsmöglichkeiten (indexed / materialized views, ...). Auch der Zugriff auf die Datenbank selbst (welche Queries werden wie gefeuert) ist dabei von Belang.

        Analysiere die Anwendungsfälle (Use Cases) für deine Anwendung und komme evt. mit diesem Ergebnis wieder hier ins Forum zurück.

        Ciao, Frank

        1. Hi Frank

          es ist eigentlich eine natürliche Aufgabe einer "Datenbank" viele bis sehr viele Datensätze zu verwalten. Ob die in 2 Tabellen stehen oder in einer sollte imho absolut irrelevant sein.

          Ist es nicht wirklich, zumindest nicht wenn du Indizes benutzt. Das sind im Regelfall ja Bäume. Nehmen wir zur Vereinfachung mal an, Binärbäume, spielt aber keine grosse Rolle. Bei einer Million Datensätzen bräuchtest du ungefähr 20 Stufen im Baum, bei 2 Millionen Datensätzen 21. Würdest du die auf 2 Tabellen verteilen, hättest du 2 * 20 Stufen im Baum.

          Gruss Daniela

          1. Hi,

            okay, das hatte ich so schnell nicht bedacht ... ein Grund mehr, die Daten in einer Tabelle zu lassen. Da gab's doch mal so einen Spruch, du sollst nicht gewaltsam trennen, was zusammen gehört ...  wie ging der noch genau??? ;-)

            Danke für den Hinweis.

            Ciao, Frank

            1. Hallo.

              Da gab's doch mal so einen Spruch, du sollst nicht gewaltsam trennen, was zusammen gehört ...  wie ging der noch genau??? ;-)

              "Besser arm dran als Arm ab."
              MfG, at

  3. echo $begrüßung;

    Ich entwickele gerade mit einem Arbeitskollegen einen Anzeigenmarkt mit insgesamt 20 verschiedenen Märkten (z.B. Automarkt, Immobilien, Telekommunikation etc.)

    Welche Beziehungen bestehen denn zwischen den einzelnen Märkten? Ich nehme an, keine direkten. Wenn also jemand nach einem Auto sucht, wird er diese Abfrage sicher nicht mit Immobilien verknüpfen wollen. Demzufolge würde ich eine Tabelle pro Markt nehmen.

    Anders sieht die Sache allerdings aus, wenn nach irgendwelchen Meta-Informationen gesucht werden soll, wie z.B. alle Anzeigen von 'Benutzername'. Dazu kommt noch die Frage, ob das nur gelegentlich zu administrativen Zwecken geschehen soll oder ob das auch die Anwender machen sollen.

    Lohnt sich da also vielleicht noch eine extra Benutzertabelle?

    Hier wird ja jede Rubrik andere Merkmale haben: Autos z. B. Kilometerstand, Innenfarbe, Aussenfarbe, Metalliclackierung, Baujahr, Klimaanlage, etc.

    Hier fallen mir zwei Ansätze ein.
    1.) für jedes Merkmal eine Spalte in der jeweiligen Markt-Tabelle
    2.) zwei extra Tabellen mit zum einen dem Merkmalnamen (plus Verweis zum Markt, der das Merkmal verwendet) und zum anderen Daten zum Merkmal (incl. Verweis auf Anzeige und Merkmalname). Möglicherweise sind hier für jeden Markt eigene Tabellen angebracht, obwohl die Daten schon eindeutig zugeordnet werden können, damit nicht zum Beispiel ein Write-Lock auf die Merkmale sämtliche Märkte ausbremst.

    Vorteil von Methode 1: Man spart sich Abfragen, man erhält pro Anzeige einen Datensatz.
    Nachteilig ist möglicherweise später die starre Struktur.

    Der Vorteil von Methode 2 ist die einfache Erweiterbarkeit um Merkmale. Nachteilig ist, dass man eine Abfrage für die Anzeige benötigt und eine für die Merkmale, die dann mehrere Datensätze liefert. Hier wird dann ggf. mehr Aufwand beim Darstellen benötigt.

    Wir rechnen später mit weit mehr als 100.000 Anzeigen pro Markt.

    Ich tendiere dann eher zu Variante 1.

    echo "$verabschiedung $name";

  4. Früher oder später werdet ihr eventuell folgende PHP-Routine schätzen lernen...
    Der mySQL-Befehl EXPLAIN zeigt an, wie eine Datenbank-Abfrage umgesetzt wird - vorallem bei welchen Tabellen eine Anfrage sehr lange dauert und wo der Einsatz von Indezes eine Steigerung bringt.
    Die PHP-Routine stellt das Ganze etwas übersichtlicher dar.

    Zur Funktion:
    analyseQuery (
    Datenbank,
    SQL-Abfrage zB "SELECT id FROM table1 AS a1...",
    mode = 1 wenn die Anzahl der zutreffenden Zeilen ermittelt werden soll, daß entspricht dann einer realen Abfrage und kann einiges dauern...
    )

    Optimieren von Datenbanken geht nicht, ohne daß man sich Gedanken gemacht hat über INDEZES, letztlich habe ich manchmal Datenbank-Abfragen gemacht, die tausendmal schneller liefen, wenn ich vorher einen Index 'created' und ihn danach wieder 'gedropped' habe.

    function analyseQuery ($db, $query, $mode = 0)
    {
      $ergq = mysql_query("EXPLAIN $query",$db);
      print "<table border="1" cellspacing="0">";
        print "<tr>";
        print "<td colspan="8" class="tinytable">".htmlentities($query)."</td>";
        print "</tr>";
        print "<tr>";
        print "<td class="tinytable">table</td>";
        print "<td class="tinytable">type</td>";
        print "<td class="tinytable">possible_keys</td>";
        print "<td class="tinytable">key</td>";
        print "<td class="tinytable">key_len</td>";
        print "<td class="tinytable">ref</td>";
        print "<td class="tinytable">rows</td>";
        print "<td class="tinytable">Extra</td>";
        print "</tr>";
      $rowsprod = 1;
      while ($dsatz = mysql_fetch_array($ergq))
      {
        $rows = $dsatz["rows"];
        $rowsprod *= $rows;
        print "<tr>";
        print "<td class="tinytable">".$dsatz["table"]."</td>";
        print "<td class="tinytable">".$dsatz["type"]."</td>";
        print "<td class="tinytable">".$dsatz["possible_keys"]."</td>";
        print "<td class="tinytable">".$dsatz["key"]."</td>";
        print "<td class="tinytable">".$dsatz["key_len"]."</td>";
        print "<td class="tinytable">".$dsatz["ref"]."</td>";
        print "<td class="tinytable">$rows</td>";
        print "<td class="tinytable">".$dsatz["Extra"]."</td>";
        print "</tr>";
      }
        print "<tr>";
        print "<td colspan="8" class="tinytable">Anzahl Abfragen = $rowsprod</td>";
        print "</tr>";
      if ($mode == 1)
      {
        $ergqr = mysql_query("$query", $db);
        $c = mysql_num_rows($ergqr);
        print "<tr>";
        print "<td colspan="8" class="tinytable">Anzahl Treffer = $c</td>";
        print "</tr>";
      }
      print "</table>";
    }