Nico: Performance bei abgleich von 2 Tabellen in msql

Hallo!

Ich versuche unterschiedliche Datensätze in zwei Tabellen mit jeweils etwa 65.000 Datenzeilen zu ermitteln und scheitere an der Umsetzung einer praktikablen Lösung, die mir bei Aufruf kein Timeout beschert.

Hier mal mein Ansatz:

"select * from mitgliederlisten_backup left join mitgliederlisten on mitgliederlisten_backup.IDnr=mitgliederlisten.IDnr where mitgliederlisten.IDnr is null"

Möglicherweise ist der genrell Ansatz mittels join falsch, aber da wüßte ich gerne mal euren Rat welcher msql-Syntax nicht nur zur Lösung, sondern zu schnellsten lösung führt.

  1. Hi!

    Möglicherweise ist der genrell Ansatz mittels join falsch, aber da wüßte ich gerne mal euren Rat welcher msql-Syntax nicht nur zur Lösung, sondern zu schnellsten lösung führt.

    Abfragesyntax allein hilft da nicht. Was sagt der Ausführungsplan, den du mit einem vorangestellten EXPLAIN bekommst? Konnte MySQL beispielsweise Indexe nutzen?

    Eine Alternative zum Join wäre eine Subquery. EXISTS in Verbindung mit einer Correlated Subquery könnte ich mir vorstellen.

    Eine generell gültige Antwort zu Performancefragen kann man nicht geben. Der Optimizer entscheidet zum Beispiel nicht nur anhand von nutzbaren Indexen, sondern auch solchen Größen wie der Anzahl der Datensätze in der Tabelle, welche Strategie zur Ergebnisfindung er verfolgt.

    Lo!

    1. Moin!

      Möglicherweise ist der genrell Ansatz mittels join falsch, aber da wüßte ich gerne mal euren Rat welcher msql-Syntax nicht nur zur Lösung, sondern zu schnellsten lösung führt.

      Abfragesyntax allein hilft da nicht. Was sagt der Ausführungsplan, den du mit einem vorangestellten EXPLAIN bekommst? Konnte MySQL beispielsweise Indexe nutzen?

      Das y fehlt eventuell absichtlich: http://en.wikipedia.org/wiki/MSQL

      Eine Alternative zum Join wäre eine Subquery. EXISTS in Verbindung mit einer Correlated Subquery könnte ich mir vorstellen.

      Datenbanken haben es immer schwerer, etwas nichtexistentes zu finden. Auf existierende Datensätze zeigen idealerweise Indices. Auf Nichtexistentes zeigt ... nichts.

      Eine generell gültige Antwort zu Performancefragen kann man nicht geben. Der Optimizer entscheidet zum Beispiel nicht nur anhand von nutzbaren Indexen, sondern auch solchen Größen wie der Anzahl der Datensätze in der Tabelle, welche Strategie zur Ergebnisfindung er verfolgt.

      Da es hier anscheinend um ein Synchronisationsproblem zwischen Backup und Original geht, sollte man in jedem Fall auch über eine Änderung des programmatischen Ansatzes nachdenken, indem man den Sync-Workflow in Daten schreibt, die die Fragen des Syncs dann wieder performant beantworten könnten.

      Auf der anderen Seite: Zweimal 70k Datensätze ist doch eigentlich ein Witz, warum sollte irgendein heutiger Computer dabei ein Problem haben? Außer man macht wirklich grobe Fehler bei der Abfrage.

      - Sven Rautenberg

      1. Hi!

        Eine Alternative zum Join wäre eine Subquery. EXISTS in Verbindung mit einer Correlated Subquery könnte ich mir vorstellen.
        Datenbanken haben es immer schwerer, etwas nichtexistentes zu finden. Auf existierende Datensätze zeigen idealerweise Indices. Auf Nichtexistentes zeigt ... nichts.

        Wenn man etwas sucht, weiß man vorher nie, ob es vorhanden ist oder nicht. In einer sortierten Menge, wie sie ein Index darstellt, ist es recht schnell möglich, etwas Vorhandenes zu finden. Es gibt da ja bekannte Verfahren, wie man sich in wenigen Schritten einem Wert annähert. Mit nur geringfügig mehr Aufwand sollte sich feststellen lassen, dass man einen Wert findet, der zu klein ist und dann einer kommt, der zu groß ist und somit die Nichtexistenz feststellen können. Oder übersehe ich da etwas Grundlegendes?

        Lo!

      2. Auf der anderen Seite: Zweimal 70k Datensätze ist doch eigentlich ein Witz, warum sollte irgendein heutiger Computer dabei ein Problem haben? Außer man macht wirklich grobe Fehler bei der Abfrage.

        Ich hatte da schon den Fall dass es halt nicht zweimal 70k waren sondern 70k hoch zwei. Da wurde das komplette Kreuzprodukt gebildet und dann da drin erst gesucht. Dann wirds schon ne krasse Angelegenheit.
        Die Optimierer spinnen in gewissen Konstellationen schon gelegentlich.
         Dann mal versuchen die Indexe neu aufzubauen, bzw. überhaupt erst aufbauen aber ich nehm an auf einer ID liegt eh ein primary key.

  2. Hallo,

    vergleich doch nur mal die ersten hundert Datensätze miteinander (TOP bzw LIMIT, jenachdem was dein MSQL ist). Vielleicht ist ja auch nur eine der Tabellen exklusiv gesperrt.

    Mit welchem Programm machst du die Abfrage und wie lautet die Fehlermeldung genau?

    Die Spalte IDnr ist wahrscheinlich Teil des Primary Keys (also eines Unique Index), von daher dürfte der Query Optimizer einen Index verwenden.

    SELECT * ist suboptimal, es selektiert alle Spalten von BEIDEN Tabellen. Eine der beiden Tabellen (die linke) würde ausreichen und die Menge an zu lesenden Daten beschränken.

    EXISTS wäre auch um einiges praktischer als der Join.

    Ciao, Frank