Perché SELECT * dovrebbe essere molto più veloce di SELECT foo?


28

Considera una tabella di valori e hash, in questo modo:

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

La seguente query termina in 0,00 secondi:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

Tuttavia, questa query richiede 3 minuti e 17 secondi:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

Vedo che mentre la query è in esecuzione l'elenco dei processi lo mostra come stato Sorting result. La situazione è completamente riproducibile. Si noti che esiste un altro processo che esegue continuamente INSERToperazioni sulla tabella.

Perché l'esecuzione della *query più specifica richiederebbe più tempo della query? Ho sempre creduto che le *query dovessero essere evitate specificamente per motivi di prestazioni.


7
Le prime istruzioni usano molto probabilmente l'indice della chiave primaria su idper trovare la prima riga. Il secondo deve ordinare il risultato completo nella valcolonna (non indicizzata) .
a_horse_with_no_name

8
La ORDER BY NUMBERsintassi è piuttosto soggetta a errori.
usr

2
Aggiungendo al tuo ultimo commento, SELECT *combinato con un indice di colonna in ORDER BYè offuscare quale colonna viene ordinata - un altro motivo per evitare *s ...
LC.

@lc., che vuoi dire?
Pacerier,

@Pacerier Intendo che *non è esplicito. Quindi dire "dammi tutte le colonne e ordinare per il terzo" è deterministico quanto dire "vai al supermercato e dimmi quanti semafori hai superato"
LC.

Risposte:


33

La frase si ORDER BY 1riferisce a diverse colonne; nel primo lo sarà id, nel secondo val. Poiché idè la chiave verrà indicizzata e order bysarà una quantità banale di lavoro. Per order by val, tuttavia, il sistema dovrà recuperare ogni riga, ordinare la tabella completa per val, quindi scegliere solo una di quelle righe.

Cambia entrambe le query in order by ide penso che i tuoi tempi di esecuzione saranno quasi identici.


3
A volte le domande più difficili sono quelle che ci stanno fissando in faccia. Grazie Michael!
dotancohen,

7

La differenza di prestazioni nella tua query è ben spiegata da MG. Ho intenzione di affrontare questo:

Ho sempre creduto che * le query dovessero essere evitate specificamente per motivi di prestazioni.

select *non comporta sanzioni particolari da solo, è problematico se usato in modo improprio. In una query a tabella singola funziona perfettamente. ora unisci quella tabella a un'altra con 20 colonne e successivamente aggiungi join a 5 altre tabelle con molte colonne ciascuna. ORA è un problema. Così sono le persone che insegnano in generale, gli aiuti alla banda "non fanno mai X" senza spiegare il perché.


3
SELECT *potrebbe essere un problema anche per una query a tabella singola. Ad esempio, SELECT * FROM hashes ORDER BY val;probabilmente eseguirà una scansione completa della tabella e quindi un ordinamento mentre SELECT val FROM hashes ORDER BY val;eseguirà solo una scansione dell'indice completa e nessun ordinamento (supponendo che esista un indice su val). Quindi, non fa mai male selezionare solo i risultati di cui abbiamo bisogno.
ypercubeᵀᴹ


@ypercube, non che si verificano anche se il nostro select(*)è usato solo come un sub -Selezionare? Dal momento che è una selezione integrata, MySQL non sarebbe abbastanza intelligente da capire le colonne reali che devono essere selezionate?
Pacerier

@Pacerier mysql optimizer ha diversi livelli di "intelligenza", a seconda della versione che stai utilizzando. In gerneal, era piuttosto stupido per quanto riguarda le subquery nidificate, quindi tutto ciò che potevi aiutarlo, era buono.
ypercubeᵀᴹ

@ypercube, Ah, se solo è intelligente come pgsql.
Pacerier,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.