Sottoquery con EXISTS vs IN – MySQL

Di seguito due query sono sottoquery. Entrambi sono uguali ed entrambi funzionano bene per me. Ma il problema è che la query del Metodo 1 richiede circa 10 secondi per l’esecuzione mentre la query Metodo 2 richiede meno di 1 secondo.

Sono stato in grado di convertire la query del metodo 1 nel metodo 2 ma non capisco cosa sta succedendo nella query. Ho cercato di capirlo da solo. Mi piacerebbe davvero imparare qual è la differenza tra le due domande sottostanti e come si verifica il guadagno in termini di prestazioni? qual è la logica dietro?

Sono nuovo di queste tecniche avanzate. Spero che qualcuno mi aiuti qui. Dato che ho letto i documenti che non mi danno un indizio.

Metodo 1:

SELECT * FROM tracker WHERE reservation_id IN ( SELECT reservation_id FROM tracker GROUP BY reservation_id HAVING ( method = 1 AND type = 0 AND Count(*) > 1 ) OR ( method = 1 AND type = 1 AND Count(*) > 1 ) OR ( method = 2 AND type = 2 AND Count(*) > 0 ) OR ( method = 3 AND type = 0 AND Count(*) > 0 ) OR ( method = 3 AND type = 1 AND Count(*) > 1 ) OR ( method = 3 AND type = 3 AND Count(*) > 0 ) ) 

Metodo 2:

 SELECT * FROM `tracker` t WHERE EXISTS ( SELECT reservation_id FROM `tracker` t3 WHERE t3.reservation_id = t.reservation_id GROUP BY reservation_id HAVING ( METHOD = 1 AND TYPE = 0 AND COUNT(*) > 1 ) OR ( METHOD = 1 AND TYPE = 1 AND COUNT(*) > 1 ) OR ( METHOD = 2 AND TYPE = 2 AND COUNT(*) > 0 ) OR ( METHOD = 3 AND TYPE = 0 AND COUNT(*) > 0 ) OR ( METHOD = 3 AND TYPE = 1 AND COUNT(*) > 1 ) OR ( METHOD = 3 AND TYPE = 3 AND COUNT(*) > 0 ) ) 

Un Explain Plan avrebbe mostrato perché esattamente dovresti usare Exists . Di solito la domanda arriva Exists vs Count(*) . Exists è più veloce. Perché?

  • Per quanto riguarda le sfide presenti da NULL: quando la sottoquery restituisce Null , per IN l’intera query diventa Null . Quindi è necessario gestire anche quello. Ma usando Exist , è semplicemente un false . Molto più facile da affrontare. Simply IN non può confrontare nulla con Null ma può Exists .

  • es. Exists (Select * from yourtable where bla = 'blabla'); si ottiene vero / falso nel momento in cui un colpo viene trovato / abbinato .

  • In questo caso IN prende la posizione del Count(*) per selezionare TUTTE le righe corrispondenti in base al WHERE perché confronta tutti i valori.

Ma non dimenticare questo:

  • EXISTS viene eseguito ad alta velocità contro IN : quando i risultati della subquery sono molto grandi.
  • IN porta avanti EXISTS : quando i risultati della sottoquery sono molto piccoli.

Riferimento a per maggiori dettagli:

  • sottoquery utilizzando IN .
  • IN – Ottimizzazione subquery
  • Join vs sub-query .

Il metodo 2 è veloce perché utilizza l’operatore EXISTS , dove I MySQL non carica alcun risultato. Come menzionato anche nel tuo documento , omette qualsiasi cosa ci sia nella clausola SELECT . Verifica solo il primo valore che soddisfa i criteri, una volta trovato imposta la condizione TRUE e si sposta per un’ulteriore elaborazione.

Dall’altro lato, il Metodo 1 ha l’operatore IN che carica tutti i valori possibili e poi lo abbina. La condizione è impostata su TRUE solo quando viene trovata una corrispondenza esatta che è un processo che richiede tempo.

Quindi il tuo metodo 2 è veloce.

Spero che sia d’aiuto…

Il secondo metodo è più veloce perché hai questo come “WHERE t3.reservation_id = t.reservation_id”. Nel primo caso la subquery deve eseguire una scansione completa nella tabella per verificare le informazioni. Tuttavia con il metodo 2o la sottoquery sa esattamente cosa sta cercando e una volta trovata viene verificata la condizione di avere allora.

La loro documentazione ufficiale. Ottimizzazione SubQuery con esistente