Frage

Die folgende Abfrage hängt: (obwohl Subqueries separat perfomed sind in Ordnung)

Ich weiß nicht, wie das machen Tabelle ok aussehen erklären. Wenn mir jemand sagt, ich werde es aufzuräumen.

select
sum(grades.points)) as p,  
from assignments 
left join grades using (assignmentID) 
where gradeID IN 

(select grades.gradeID 
from assignments 
left join grades using (assignmentID) 
where ... grades.date <= '1255503600' AND grades.date >= '984902400' 
group by     assignmentID order by grades.date DESC);

Ich denke, das Problem mit der ersten Klassen-Tabelle ist ... ALL die Art mit, dass viele Zeilen scheint die Ursache zu sein .. Alles, was indiziert ist.

Ich hochgeladen die Tabelle als ein Bild. Formatierung kann nicht richtig machen: http://imgur.com/AjX34.png

Wir wollten ein Kommentator die volle where-Klausel:

explain extended select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
where gradeID IN 
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC);
War es hilfreich?

Lösung

Angenommen, Sie einen echten Datenbank (dh eine beliebige Datenbank außer MySQL, aber ich werde Postgres als Beispiel), um diese Abfrage zu tun:

SELECT * FROM ta WHERE aid IN (SELECT subquery)

eine echte Datenbank bei der Unterabfrage aussehen würde und schätzt seine rowcount:

  • Wenn die rowcount klein ist (sagen wir, weniger als ein paar Millionen)

Es würde die Unterabfrage ausgeführt wird, dann ein im Speicher-Hash-IDs, bauen, die auch sie einzigartig macht, die ein Merkmal von IN ist ().

Wenn dann die Anzahl der Zeilen von ta gezogen ist ein kleiner Teil von ta, würde es einen geeigneten Index verwenden, um die Zeilen zu ziehen. Oder, wenn ein großer Teil der Tabelle ausgewählt wird, es wäre es nur ganz scannen und Lookup jede ID in der Hash, der sehr schnell ist.

  • Wenn jedoch die Unterabfrage rowcount ist recht groß

Die Datenbank würde wahrscheinlich umschreiben es als ein Merge JOIN, das Hinzufügen einer Sortierung + Einzigartig in der Unterabfrage.

Sie sind jedoch mit MySQL. In diesem Fall wird es irgendetwas davon nicht tun (es ist Gonna wieder führt die Unterabfrage für jede Zeile der Tabelle), so wird es 1000 Jahre dauern. Es tut uns Leid.

Andere Tipps

Siehe „Die unerträgliche Langsamkeit IN“: http://www.artfulsoftware.com/infotree/queries.php#568

Super chaotisch, aber: (Danke für die Hilfe aller)

   SELECT * 
   FROM grades
   LEFT JOIN assignments ON grades.assignmentID = assignments.assignmentID
   RIGHT JOIN (

   SELECT g.gradeID
 FROM assignments a
 LEFT JOIN grades g
 USING ( assignmentID ) 
 WHERE a.classID =  '7815'
 AND (
 a.type =30170
 )
 AND g.contactID =7141
  g.points
 REGEXP  '^[-]?[0-9]+[-]?'
 AND g.points !=  '-'
 AND g.points !=  ''
 AND (
 g.pointsposs IS NULL 
 OR g.pointsposs =  ''
 )
 AND g.date <=  '1255503600'
 AND g.date >=  '984902400'
 GROUP BY assignmentID
 ORDER BY g.date DESC
 ) AS t1 ON t1.gradeID = grades.gradeID

Wenn Sie Ihre Unterabfrage in Ordnung durchführt, wenn es separat ausgeführt wird, dann versuchen, ein eher mit JOIN als IN, wie folgt aus:

select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
join
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC) using (gradeID);

Es ist wirklich nicht genug Informationen, um Ihre Frage zu beantworten, und Sie haben eine setzen ... in der Mitte der Where-Klausel, die seltsam ist. Wie groß sind die beteiligten Tabellen und was sind die Indizes?

Having said that, wenn es zu viele Begriffe in einem in-Klausel können Sie ernsthaft verschlechterte Leistung sehen. Ersetzen Sie die Verwendung in mit einem rechten verbinden .

Für den Anfang der Tabelle as_types in der in-Klausel nicht verwendet wird. Links Beitritt dient so keinen Zweck, es loszuwerden.

Damit bleibt die in Klausel aus der äußeren Abfrage nur die Zuweisungen und Typen Tabelle mit. Klar, dass die wheres gehören die modify Zuordnungen in der Where-Klausel für die äußere Abfrage. Sie sollten alle der in dem Typen = bewegen, was in die on-Klausel von der linken Seite Noten verbinden.

Die Abfrage ist ein wenig schwer zu folgen, aber ich vermute, dass die Unterabfrage überhaupt nicht erforderlich ist. Es scheint, wie Ihre Abfrage ist im Grunde so:

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE gradeID IN 
(
SELECT grades.gradeID
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE your_conditions = TRUE
);

Aber, bist du nichts zu tun wirklich Lust in der where-Klausel in der Unterabfrage. Ich vermute, etwas mehr wie

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
GROUP BY groupings
WHERE your_conditions_with_some_tweaks = TRUE;

würde genauso gut funktionieren.

Wenn ich einige wichtige Logik fehlt hier bitte kommentieren zurück und ich werde editieren / löschen Diesen Beitrag.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top