Domanda

Ho bisogno di consigli per quanto riguarda le prestazioni di sottoselezione in MySQL. Per un motivo che non posso modificare, non riesco a utilizzare JOIN per creare un filtro query, posso solo aggiungere un'altra clausola AND in WHERE.

Qual è la performance di:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

rispetto a:

select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Nota che c'è un numero relativamente piccolo di progetti mentre is_template = 1, e potrebbe esserci un gran numero di progetti in cui is_template < > 1.

Esiste un altro modo per ottenere lo stesso risultato senza sottoselezioni se non posso cambiare altro che filtrare?

È stato utile?

Soluzione

Credo che il secondo sia più efficiente in quanto richiede solo una selezione, ma per essere sicuri, dovresti SPIEGARE ogni query e controllare i risultati.

EXPLAIN select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

EXPLAIN select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Altri suggerimenti

Quanta differenza c'è tra i due potrebbe dipendere molto da quale " alcuni criteri " è e quali opportunità di utilizzare gli indici che fornisce. Ma nota che non sono equivalenti in termini di risultati se ci sono attività che non hanno progetti. Il secondo è equivalente a questo:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id in (select id from project where project.is_template <> 1);

Penso che il primo potrebbe ridimensionarsi meglio:

Quando si esegue un join, internamente mysql crea una sorta di tabella temporanea composta dalle due tabelle unite in base alle condizioni di join specificate. Non stai dando una condizione di join, quindi creerà una tabella temporanea con tutte le attività elencate per tutti i progetti. Sono abbastanza sicuro (ma controlla con lo strumento spiegazione) che lo fa prima di applicare le clausole where.

Risultato: se ce ne sono 10, avrà 10 * 10 righe = 100. Puoi vedere come questo diventa grande quando i numeri aumentano. Quindi applica il dove a questa tabella temporanea.

Al contrario, la sottoquery seleziona solo le righe pertinenti da ciascuna tabella.

Ma a meno che il ridimensionamento non sia un problema, non penso che sia davvero importante.

Evita sottoquery come la peste nelle versioni di MySQL < 6.0 e dubito che tu stia usando 6.0 considerando che è ancora nella fase alfa dello sviluppo. AFAIK, l'ottimizzatore MySQL non gestisce bene le subquery. Alcuni lavori importanti sono stati dedicati al rinnovamento dell'ottimizzatore per 6.0 e le query secondarie funzionano molto meglio ora, ma questi cambiamenti non sono passati alla serie 5.0 o 5.1.

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