2016-04-20 4 views
0

Ich habe zwei Tabellen mit einer verbindenden Spalte mit einer Viele zu vielen Beziehung. In jeder Tabelle gibt es ein paar hunderttausend Datensätze. Ich sehe eine sehr langsame Abfrageleistung und habe Probleme, das Problem zu identifizieren.MySQL viele zu viele Tabelle verbinden langsame Leistung

Table_A:

+---------------------------+-------------+---------------+ 
| ID | Name varchar (30) | Age int(3) | Status int(1) | 
+----+----------------------+-------------+---------------+ 
| 1 | Tom     | 23   | 1    | 
| 2 | Jerry    | 34   | 2    | 
| 3 | Smith    | 21   | 1    | 
| 4 | Ben     | 46   | 5    | 
+---------------------------+-------------+---------------+ 

Table_B:

+---------------------------+-------------+---------------+ 
| ID | Name varchar (30) | Sign int(3) | Status int(1) | 
+----+----------------------+-------------+---------------+ 
| 1 | Tom     | 12   | 1    | 
| 2 | Smith    | 8   | 1    | 
| 3 | Tom     | 3   | 0    | 
| 4 | Tom     | 10   | 1    | 
+---------------------------+-------------+---------------+ 

Ich brauche das Alter der einzelnen Namen in der Tabelle A zu erhalten, die mit einem Spiel auf Namen mindestens eine Zeile in Tabelle B und einem Status (Tabelle B) von 1.

ich habe versucht:

SELECT Age FROM Table_A 
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name 
WHERE Table_B.Status=1; 

Diese Abfrage dauert so lange, dass ich nicht darauf gewartet habe, dass sie zurückkommt. ich dann versucht:

SELECT DISTINCT Age FROM Table_A 
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name AND Table_B.Status=1; 

, die sehr schnell zurück. ich weiter getestet und versucht:

SELECT DISTINCT Age FROM Table_A 
LEFT JOIN Table_B ON Table_A.Name=Table_B.Name 
WHERE Table_B.Status=1; 

das wieder kam nicht zurück.

Ich bin verwirrt, was hier vor sich geht.

In der letzten Abfrage sollte die WHERE-Bedingung nicht die gleiche wie die JOIN ON-Bedingung der vorherigen Abfrage (Status = 1) handeln?

Warum gibt SELECT DISTINCT Ergebnisse zurück, während ohne DISTINCT der Prozess ewig dauert?

+0

Zunächst möchten Sie wahrscheinlich innere Verbindung statt der linken äußeren verwenden. – mustaccio

+0

Beide haben mir das gleiche Ergebnis gegeben. – webish

+0

Es gibt drei Fragen, die ich hier stellen möchte. (1) Warum schließen Sie sich sogar dem Namen an? (2) Was sind Ihre Primärschlüssel und was sind Ihre Fremdschlüssel? Und zuletzt sind das nicht viele, wo ist dein dritter Tisch? – dimm

Antwort

0

Ohne einen EXPLAIN-Plan (oder was auch immer das MySQL-Äquivalent ist) zu sehen, ist es unmöglich, dies mit Sicherheit zu sagen.

Meine Vermutung wäre, dass der Server weiß, dass Ihre OUTER JOIN' to table B is completely irrelevant when you use SELECT DISTINCT , so it just runs against table A and gets the Age values from there without even performing the JOIN . Do you see why the OUTER JOIN 'irrelevant ist?

In der ersten Abfrage muss der Server die JOIN durchführen, um die richtige Anzahl von Zeilen zurück zu bekommen.

Wenn Sie die zusätzliche Logik zu Ihrer WHERE Klausel in der letzten Abfrage Sie effektiv in ein INNER JOIN gedreht habe hinzuzufügen, so dass nun die JOIN wieder geschehen hat, und es dauert eine lange Zeit.

0

Vergewissern Sie sich, Indizes setzen auf den Table_A.Name, Table_B.Name und Table_B.Status Spalten

0

Zuerst Sie kein LEFT JOIN benötigen, weil Sie nur Streichhölzer Pflege:

SELECT a.Age 
FROM Table_A a JOIN 
    Table_B b 
    ON Table_A.Name = b.Name 
WHERE b.Status = 1; 

Für diese Abfrage kann die Vorteile von Indizes auf Table_B(status, name) und Table_A(Name, Age) nutzen.

0

Für eine Viele-zu-Viele-Tabelle, keine AUTO_INCREMENT. Lassen Sie die PRIMARY KEY beide anderen IDs enthalten. Habe einen anderen Index. Verwenden Sie InnoDB.

Siehe More details, plus rationale.