2009-05-14 12 views
24

Una delle mie query su MySQL 5.0.45 è in esecuzione lenta nella fase di "invio dei dati". La query è una semplice selezione, restituisce circa 300 campi ID interi come set di risultati.MySql - fase di invio lento dei dati

 
mysql> SELECT source_id FROM directions WHERE (destination_id = 10); 
+-----------+ 
| source_id | 
+-----------+ 
|   2 | 
|   8 | 
... 
|  2563 | 
+-----------+ 
341 rows in set (2.13 sec) 

Sono notare sicuro perché è "l'invio dei dati" fase così lento e cosa si può fare per rendere più veloce. Si noti che sto eseguendo questa query sul prompt di MySQL sul server stesso, quindi non mi aspetto davvero che passi così tanto tempo in "invio di dati". Qualche indizio?

Se aiuta, ho 3 campi di testo su questo tavolo, ma dal momento che non vengono selezionati, mi aspetto che non sono causa di questa lentezza.

Questa query viene eseguita migliaia di volte al giorno e non può davvero permettersi di spendere 2 secondi su di esso di volta in volta.

risultato Profiling:

 
mysql> show profile for query 4; 
+--------------------------------+----------+ 
| Status       | Duration | 
+--------------------------------+----------+ 
| (initialization)    | 0.000003 | 
| checking query cache for query | 0.000051 | 
| checking permissions   | 0.000007 | 
| Opening tables     | 0.000011 | 
| System lock     | 0.000005 | 
| Table lock      | 0.000023 | 
| init       | 0.00002 | 
| optimizing      | 0.00001 | 
| statistics      | 0.00006 | 
| preparing      | 0.000014 | 
| executing      | 0.000005 | 
| Sending data     | 2.127019 | 
| end       | 0.000015 | 
| query end      | 0.000004 | 
| storing result in query cache | 0.000039 | 
| freeing items     | 0.000011 | 
| closing tables     | 0.000007 | 
| logging slow query    | 0.000047 | 
+--------------------------------+----------+ 
18 rows in set (0.00 sec) 

UPDATE: ho inciampato sul seguente URL che dice

 
Each time means the time elapsed between the previous event and the new event. So, the line: 
| Sending data | 0.00016800 | 
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query. 

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

Qualcuno può convalidare?

+7

L'affermazione non è vera sulla pagina collegata. Se esegui una 'SHOW PROCESSLIST' mentre la query è in esecuzione, mostrerà che la query è effettivamente nello stato ** Invio di dati **. (Non nel precedente). - E per favore nessuno dica che la lista dei processi mostra il passaggio * successivo * nell'esecuzione. :) – vbence

+0

@vbence: hai mai visto una query che richiede più di pochi utenti per l'esecuzione? La teoria di cui sopra ha un senso. –

+0

@ user9111337 Oh si. Le istruzioni aggregate (GROUP BY) con la clausola WHERE di solito generano selezioni che non possono essere risolte usando un indice (EXPLAIN ... dirà "USANDO DOVE") - se la tabella è abbastanza grande, ciò può richiedere diversi minuti. - Come viene segnalato? Puoi vederlo da solo provando l'opzione 'SHOW PROCESSLIST'. – vbence

risposta

1

Hai indici su questo tavolo? Hai detto che restituisce circa 300. Ma quanti devono cercare per trovare quelli 300?

15

Un piano di spiegazioni è in genere il miglior punto di partenza ogni volta che si ha una query lenta. Per ottenerne uno, esegui

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10); 

Questo mostrerà una tabella che elenca i passaggi necessari per eseguire la query. Se viene visualizzato un valore elevato nella colonna "righe" e NULL nella colonna "chiave", ciò indica che la query deve eseguire la scansione di un numero elevato di righe per determinare quali restituire.

In tal caso, l'aggiunta di un indice su Destination_id dovrebbe accelerare drasticamente la tua ricerca, ad un certo costo per inserire ed eliminare la velocità (in quanto l'indice sarà anche bisogno di essere aggiornato).

+10

Mentre sono d'accordo che una query EXPLAIN/DESCRIBE è il modo per trovare come risolverlo, non hai veramente descritto a cosa serve la fase "invio dei dati". Vedi http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html –

-2

La query spende da 2.127019 a eseguire la query. Ciò è probabilmente dovuto al fatto che hai una grande quantità di dati e manchi un indice nella colonna destination_id. Prova:

CREATE INDEX index_destination_id ON indicazioni (destination_id);

Quindi la richiesta verrà eseguita correttamente.

+3

Questa affermazione è FALSE vedi il mio commento sulla domanda. – vbence

+0

Ma per me, in uno scenario diverso, infatti l'aggiunta di un indice ha risolto la mia lenta query - a volte l'ovvio viene perso. –

6

Si potrebbe probabilmente guardare la parte hardware del server mysql. Come Mysql doc dice:

Invio dati

Il filo è la lettura e righe di elaborazione per un'istruzione SELECT, e l'invio di dati al client. Poiché le operazioni che si verificano durante questo stato tendono a eseguire grandi quantità di accesso al disco (letture), è spesso lo stato di funzionamento più lungo durante il ciclo di vita di una determinata query.

Quindi, se il server dispone lento disco I/O a causa della enorme di file db/tavola o l'opzione tableperfile InnoDB disabili/frammentazione/configurato in modo errato processo di crash del RAID/disk avviato (attendere che presto la morte del disco)/qualsiasi altro motivo della lentezza del I/O del disco - è potrebbe essere il motivo per aumentare drasticamente il passo "Invio di dati" in quanto in questa fase il server raccoglie tutti i dati richiesti dal disco e lo invia al client.

Ovviamente si dovrebbe cercare di ottimizzare la selezione per utilizzare gli indici per primi e assicurarsi che questo non sia un problema di programmazione in quanto ciò influisce su questo palco nella maggior parte dei casi.

0

ho avuto lo stesso problema: Invia dati era molto lento, ma ho avuto gli indici corretti ecc

Dopo molte scavare intorno, ho trovato che il mio join stava confrontando due campi che sono stati indicizzati, ma aveva diversi Collation: uno era latin1_swedish_ci e l'altro era uft8_general_ci.

Una volta che tutti e due che ho inviato al utf8 la query è stata significativamente più veloce (da 2,7 secondi a 0,002 secondi)