2013-07-22 9 views
5

Ich habe zwei Tabellen:GROUP BY Fremdschlüssel oder Primärschlüssel?

user 
======= 
id 
name 
class 

marks 
======= 
id 
user_id 
sub_id 
mark 

Benutzertabelle die Details Benutzer enthält (Schüler) Markierungen Tabelle sind die Noten eines Schülers enthält in verschiedenen Fächern mit dem Betreff id

ich Namen holen wollen, Klasse und Gesamtmarkierungen aus diesen Tabellen.

Ich habe zwei Anfragen:

1. SELECT name, class, SUM(mark) AS total FROM user 
    LEFT JOIN marks ON marks.user_id = user.id 
    GROUP BY marks.user_id 
    ///Here in GROUP BY I have used foreign key (marks.user_id) 

2. SELECT name, class, SUM(mark) AS total FROM user 
    LEFT JOIN marks ON marks.user_id = user.id 
    GROUP BY user.id 
    ///Here in GROUP BY I have used primary key (user.id) 

Beide gibt mir Daten erforderlich. Meine Frage ist welche soll ich verwenden?

Gibt es eine Regel, die besagt, dass Sie den Primärschlüssel in der Gruppe verwenden sollen, indem Sie einen OR-Fremdschlüssel in der Gruppe eingeben, indem Sie etwas Ähnliches verwenden?

+1

versuchen, die Abfrage auszuführen, die 'user.id' keinen übereinstimmenden Wert für' marks.user_id' hat. und sehen, was passiert. –

+2

Was sagt 'Explain' zu beiden Fragen? –

+0

@ 491243: Lass mich das überprüfen. –

Antwort

3

Sie sollten die Gruppierung der Version 2 mit dem Primärschlüssel verwenden. Im Allgemeinen ist es besser, die Befehle order und group by basierend auf den Spalten der Haupttabelle zu haben und nicht auf den verknüpften. Wenn Sie nach Join-Tabellenspalten sortieren oder gruppieren, muss MySQL temporäre Tabellen erstellen, die basierend auf Ihrer Datengröße leicht auf die Festplatte gelangen und einen erheblichen Leistungsengpass verursachen können.

Führen diese für die zwei Abfrage erklärt, um zu sehen, was ich sprach:

EXPLAIN SELECT name, SUM(mark) AS total FROM users 
    LEFT JOIN marks ON marks.user_id = users.id 
    GROUP BY marks.user_id; 

EXPLAIN SELECT name, SUM(mark) AS total FROM users 
    LEFT JOIN marks ON marks.user_id = users.id 
    GROUP BY users.id; 

Same sind hier zu finden: http://sqlfiddle.com/#!2/a8ece/6

+0

Danke Ich denke, das ist die Antwort, die ich wollte. :) –

0

weil der Primärschlüssel ein eindeutiger Index ist. Gruppe (Primärschlüssel)

nicht Anzahl der Zeile in der Folge reduziert

so denke ich, Sie Gruppe (Fremdschlüssel) verwenden können

6

Da Sie links getan haben beitreten sollten Sie die 2. Abfrage als marks.user_id könnte null sein

+0

Und was ist, wenn marks.user_id nicht null ist. Ich spreche von der Leistung, wenn ich riesige Daten haben werde. –

2

Ich schlage vor, dass Sie die zweite verwenden, da es einen leichten Leistungsunterschied zwischen einem Primärschlüssel-Index und jedem anderen doppelten Index gibt. Es ist sehr wahrscheinlich, dass Ihre häufigste Abfrage in dieser Tabelle darin besteht, herauszufinden, ob sich ein Benutzer in bestimmten Markierungen befindet, und diese Abfrage wird schnell ausgeführt, es sei denn, marks.user_id kann null sein.

1

Wenn ich die folgende SQL lief:

DESCRIBE SELECT name, class, SUM(mark) AS total FROM user 
LEFT JOIN marks ON marks.user_id = user.id 
GROUP BY marks.user_id; 

MySQL sagte, dass es filesort für Benutzertabelle verwendet und keine Schlüssel für die Tabelle verwendet wurden, und wenn ich folgendes ausführte:

DESCRIBE SELECT name, class, SUM(mark) AS total FROM user 
LEFT JOIN marks ON marks.user_id = user.id 
GROUP BY user.id; 

Jetzt sagte MySQL, dass es Schlüssel für beide Tabellen verwendet (anstelle von filesort). Daher denke ich, dass der zweite die empfohlene Vorgehensweise sein sollte, da filesort die Leistung beeinträchtigen kann.