Domanda

La seguente query si blocca: (anche se le sottoquery eseguite separatamente vanno bene)

Non so come rendere ok la tabella di spiegazione. Se qualcuno me lo dice, lo pulirò.

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);

Penso che il problema sia con la prima tabella dei voti ... il tipo ALL con così tante righe sembra essere la causa .. Tutto è indicizzato.

Ho caricato la tabella come immagine. Impossibile ottenere la formattazione corretta: http://imgur.com/AjX34.png

Un commentatore voleva la clausola where completa:

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);
È stato utile?

Soluzione

Supponi di utilizzare un vero database (cioè qualsiasi database tranne MySQL, ma userò Postgres come esempio) per fare questa query:

SELECT * FROM ta WHERE aid IN (SELECT subquery)

un database reale guarderebbe la sottoquery e ne stimerebbe il conteggio delle righe:

  • Se il conteggio delle righe è piccolo (diciamo, meno di qualche milione)

Eseguirà la subquery, quindi creerebbe un hash di id in memoria, che li rende anche unici, che è una caratteristica di IN ().

Quindi, se il numero di righe estratte da ta è una piccola parte di ta, userebbe un indice adatto per estrarre le righe. Oppure, se viene selezionata una parte importante della tabella, la scansionerebbe completamente e cercherebbe ogni id nell'hash, che è molto veloce.

  • Se tuttavia il conteggio delle righe della subquery è abbastanza grande

Probabilmente il database lo riscriverebbe come unione JOIN, aggiungendo un ordinamento + Unico alla sottoquery.

Tuttavia, stai usando MySQL. In questo caso, non farà nulla di tutto ciò (eseguirà di nuovo la subquery per ogni riga del tuo tavolo), quindi ci vorranno 1000 anni. Siamo spiacenti.

Altri suggerimenti

Vedi " L'insostenibile lentezza di IN " ;: http://www.artfulsoftware.com/infotree/queries.php#568

Super disordinato, ma: (grazie per l'aiuto di tutti)

   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

Se la tua sottoquery funziona bene quando viene eseguita separatamente, prova a utilizzare un JOIN anziché IN, in questo modo:

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);

In realtà non ci sono abbastanza informazioni per rispondere alla tua domanda, e hai messo un ... nel mezzo della clausola where che è strana. Quanto sono grandi le tabelle coinvolte e quali sono gli indici?

Detto questo, se ci sono troppi termini in una clausola in, puoi vedere prestazioni seriamente degradate. Sostituisci l'uso di in con un join destro .

Per cominciare, la tabella as_types nella clausola in non viene utilizzata. Lasciarlo entrare non serve a nulla, quindi liberarsene.

In questo modo la clausola in ha solo la tabella delle assegnazioni e dei voti della query esterna. Chiaramente dove si trovano le assegnazioni di modifica nella clausola where per la query esterna. Dovresti spostare tutti i gradi = qualunque dove nella clausola on della sinistra unisci ai voti.

La query è un po 'difficile da seguire, ma sospetto che la subquery non sia affatto necessaria. Sembra che la tua query sia sostanzialmente così:

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
);

Ma non stai facendo nulla di veramente fantastico nella clausola where nella sottoquery. Sospetto qualcosa di più simile a

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

funzionerebbe altrettanto bene.

Se mi manca un po 'di logica chiave, ti preghiamo di commentare di nuovo e modificherò / eliminerò questo post.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top