Bernd: SQL Abfrage über 10 und mehr Tabellen

Hallo, ich bins mal wieder 😀. Meine Daten liegen in eine SQL Datenbank in ca. 15 verschiedenen Tabellen. Ist es Sinnvoll diese mittels einer einzigen Select Abfrage zu ermitteln? Also mit SELECT und dann mittels LEFT JOIN aus den einzelnen einzubinden, oder gibt es eine andere womöglich sinnvolle Methode.

Bernd

  1. Lieber Bernd,

    merke: Es gibt nichts, was es nicht gibt. Daher gibt es garantiert eine ideale Vorgehensweise für Dein Vorhaben. Es gibt sogar die Möglichkeit, in Deinen Postings genauere Angaben zur Natur Deines Problems zu machen, damit Hilfevorschläge präziser werden können...

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix, ja das stimmt mit dem Präziser.

      Also meine Abfrage geht über 9 Tabellen. Bis jetzt habe ich kein Index angelegt.

      Eine Abfrage (immer die gleiche) dauert manchmal 0.0908 Sekunden, manchmal 30 Sekunden.

      SELECT
      ...
      
      FROM tabelle a
      
      LEFT JOIN table_2 b ON b.kennziffer = a.kennziffer 
      LEFT JOIN table_3 c ON c.kennziffer = a.kennziffer 
      LEFT JOIN table_4 d ON d.kennziffer = a.kennziffer 
      LEFT JOIN ...
      LEFT JOIN ...
      LEFT JOIN ...
      LEFT JOIN ...
      LEFT JOIN ...
      
      WHERE a.nummer=1234 AND a.name='name'
      

      so wie ich das verstehe sollte man einen index erstellen. Aber ich verstehe nicht ganz wie ich das über zwei Tabellen mache.

      Sonst würde ich für jede Tabelle einen Index anlegen.

      Bernd

      1. Eine Abfrage (immer die gleiche) dauert manchmal 0.0908 Sekunden, manchmal 30 Sekunden.

        Das hängt also vom Zustand des Caches der Datenbanken und (dem) von den Festplatten ab.

        Sonst würde ich für jede Tabelle einen Index anlegen.

        So soll das.

      2. Hallo Bernd,

        Aber ich verstehe nicht ganz wie ich das über zwei Tabellen mache

        Gar nicht. Jede einzelne Tabelle bekommt einen Index auf die Kennziffer. Wenn's geht, als Primary Key (="clustering index"), damit der Server die Daten auch in dieser Reihenfolge speichert.

        Ohne Index muss der Server jede Tabelle komplett durchlesen, um die passenden Sätze zu finden.

        Eine Abfrage (immer die gleiche) dauert manchmal 0.0908 Sekunden, manchmal 30 Sekunden.

        Wenn auch Nummer und Name gleichbleiben

        Grund 1: Cache gefüllt / nicht gefüllt
        Grund 2: Ein anderer Prozess nuckelt gerade auch an der DB
        Grund 3: Shared Server mit vielen anderen leistungshungrigen Kunden
        Grund 4: Ist der DB Server auf der gleichen Maschine wie der Webserver? Wenn nein: Netzwerk verstopft
        Grund 5: Festplattenschaden. Recht unwahrscheinlich…

        Rolf

        --
        sumpsi - posui - obstruxi
  2. Meine Daten liegen in eine SQL Datenbank in ca. 15 verschiedenen Tabellen. Ist es Sinnvoll diese mittels einer einzigen Select Abfrage zu ermitteln?

    Nur 15? Das ist gar nichts. Frag mal bei SAP…

    Soll heißen:

  3. Hallo Bernd,

    Ist es Sinnvoll diese mittels einer einzigen Select Abfrage zu ermitteln?

    Klare Antwort: Jein.

    Kleineres Beispiel: 3 Tabellen. Zwischen Tabelle 1 und 2 bestehe eine 1:0..1 Beziehung, zwischen Tabelle 1 und 3 eine 1:0..n Beziehung.

    Das "0..1" soll bedeuten: Zu jeder Row in Tabelle 1 gibt es 0 oder 1 Rows in Tabelle 2, und zu jeder Row in Tabelle 2 gibt es genau eine Row in Tabelle 1.

    Dementsprechend bedeutet "1:0..n", dass es zu einer Row in Tabelle 1 beliebig viele Rows in Tabelle 3 geben kann, auch gar keine.

    Ein Table1 LEFT JOIN Table2 ist zumeist sinnvoll. Da, wo in Table2 keine Daten stehen, kommt halt NULL raus. Und eine Row aus Table1 taucht im Ergebnis auch nur einmal auf. Es gibt Grenzfälle. Wenn die allermeisten Rows in Table1 keine Entsprechung in Table2 haben und man aus der DB die letzte Performance rausquetschen muss, kann in Table1 ein Flag "Hat Daten in Table2" sinnvoll sein und man fragt Table2 nur ab, wenn das Flag gesetzt ist. Aber wirklich, das ist ein Grenzfall. Der wird bei Dir nicht vorkommen. Es kann auch sein, dass Table2 gar keine Table ist, sondern ein View. Oder eine Table Expression (also irgendwas Gejointes), und der Server tut sich schwer, einen Satz darin zu finden. Zumeist fehlt dann einfach ein Index. Aber es mag auch Konstellationen geben, wo es einfach nicht schneller geht. Dann ist das Flag und das Teilen der Abfrage vielleicht doch wieder günstiger.

    Ein Table1 LEFT JOIN Table3 ist eine andere Sache. Angenommen, du liest aus Table1 20 Spalten und aus Table3 kommen 2 dazu. Wenn Du nun zur ID=17 in Table1 mehr als eine Row in Table3 findest, sagen wir mal 7 Stück, dann hast Du 7 Ergebniszeilen und 20 Spalten davon wiederholen sich Zeile für Zeile. Das ist zusätzlich zu übertragendes Datenvolumen und Du brauchst beim Auswerten des Ergebnisses auch eine Logik, die die Duplikate korrekt behandelt.

    Jetzt nehmen wir noch Table4 und Table5 hinzu. Diese ekelhafte ID=17 hat in Table4 3 Rows und in Table5 2 Rows. Du fragst ID=17 ab, und bekommst... 7×3×2=42 Rows. Ist das sinnvoll? Eher nicht.

    Bei 15 Tabellen multipliziert sich das weiter. Wenn die meisten der genutzten Beziehungen vom Typ 1:0..1 sind, ist es nicht so schlimm, aber jede 1:n Beziehung birgt das Risiko einer Datenflut. Hier muss man bei jeder Query einzeln nachdenken, was günstig oder ungünstig ist.

    Wenn Du nur eine einzelne ID abfragst, kann es nützlich sein, die Query in mehrere Schritte zu zerlegen. Schritt 1 behandelt nur die 1:0..1 Beziehungen und liefert damit maximal eine Zeile. Bei den 1:n Beziehungen musst Du überlegen, ob sie untereinander auch eine Beziehung haben. Wenn es zu einem Pullover Modell #4711 3 Farben und 4 Größen gibt, dann hast Du 12 Kombinationen und das kann sinnvoll sein, wenn Du für jede Kombination einen Artikelsatz hast, der Dir Preis und Lagervorrat für diese Kombi hast. Wenn es nur darum geht, zum Artikel "Pullover #4711" die Auswahllisten für Farben und Größen zu befüllen, ist es nicht sinnvoll, weil Du dann nämlich das Ergebnis auf eindeutige Farben und Größen zusammendampfen musst.

    Aber sind dann zwei einzelne Querys besser? Kommt drauf an - wenn der DB Server auf einer anderen Maschine wie der Webserver läuft, sind Querys Netzwerk-Requests und deutlich teurer, als wenn nur Interprozesskommunikation auf einer Maschine erforderlich ist.

    Es ist ein ständiges Abwägen. JOINs können redundante Daten im Ergebnis erzeugen, ein JOIN kann ein teures Ziel haben, und mehrere Querys können über Netzwerk viel Zeit für Server-Roundtrips verbrauchen.

    Optimale Datenbankprogrammierung ist eine Wissenschaft. Und ich bin bestenfalls Amateur.

    Rolf

    --
    sumpsi - posui - obstruxi