2012-06-09 17 views
5

Così qui è una tabella molto semplice 'tbl':Perché questa semplice query MySQL è così lenta?

+---------+---------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+---------+---------------------+------+-----+---------+----------------+ 
| val  | varchar(45)   | YES | MUL | NULL |    | 
| id  | bigint(20) unsigned | NO | PRI | NULL | auto_increment | 
+---------+---------------------+------+-----+---------+----------------+ 

e gli indici per esso:

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| tbl |   0 | PRIMARY |   1 | id   | A   | 201826018 |  NULL | NULL |  | BTREE  |   | 
| tbl |   1 | val  |   1 | val   | A   |  881336 |  NULL | NULL | YES | BTREE  |   | 
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

sto cercando questo semplice selezionare:

select val from tbl where val = 'iii'; 

risultato: 86.208 righe nel set (0,08 sec)

Ma quando voglio modificarlo leggermente:

select id, val from tbl where val = 'iii'; 

il risultato è: 86208 rows in set (47.30 sec)

ho un proprio indice sul coumn che qualora punti a, tutto sto modifica è la rappresentazione righe di risultati. Perché c'è un ritardo così terrificante? (Devo dire che non riesco a riprodurre questo ritardo ogni volta che voglio: anche dopo aver ripristinato la cache della query o impostato il comando 'query_cache_type = off' può essere fatto rapidamente).

+2

Si potrebbe provare a eseguire "EXPLAIN", ma si sospetta che si tratti più di un problema relativo al server. –

+0

Perché dovresti selezionare 86 mila campi e fare quello di DUE colonne? Penso che il problema qui sia la logica della query:/Forse dovresti condividere quello che vuoi ottenere? –

+0

Motore ?, prova l'indice di testo completo – jcho360

risposta

3

Senza effettivamente esaminare la configurazione del server è difficile dirlo, ma ecco un'ipotesi plausibile. In prima istanza, MySQL è in grado di soddisfare la tua query senza realmente leggere i dati della tabella. Tutte le informazioni richieste possono essere recuperate dall'indice. Si noti che la cardinalità dell'indice val è solo dell'ordine di 10 righe e che le righe saranno molto corte nell'indice.

Nel secondo caso sono richiesti dati NON nell'indice val. Ora il motore deve effettivamente trovare e leggere le righe dai dati. Qui la cardinalità è circa 250 volte più grande, e poiché l'indice recupererà le righe ordinate per val, trovare i corrispondenti valori id richiederà MOLTO salto in centinaia di concerti di dati su disco. Questo sarà molto più lento.

+0

questa è la ragione. – Sebas

+0

Sì, l'indice corretto della tupla ha fatto la cosa. Grazie e per favore visita la mia nuova domanda: http://stackoverflow.com/questions/11004651/how-to-make-well-indexed-mysql-tables-join-effectively :) –

0

Prova ad aggiungere un ORDER BY e `LIMIT alla query. Questo dovrebbe aiutare molto.

penso che se si modifica la query per questo sarà più veloce:

select id, val from tbl where val = 'iii' order by val limit 10; 
+0

"limite" limiterà solo il numero di righe recuperate ... è più veloce, ma se hai bisogno dell'intero set di dati, è inutile. d'altra parte, "ordina per" rallenterà la query, perché il server deve ordinare il set di risultati prima di inviare i dati – Barranka

+0

Ordine rallenterà la query – jcho360

+0

@Barranka: assumendo che stava selezionando tutte le righe, sì. Altrimenti stava selezionando alcune righe casuali e il database non sapeva come ottimizzarlo. – Wolph

0

Stai facendo una selezione basata su due colonne, ma nessun indice di entrambi esiste. Prova ad aggiungere un nuovo indice costituito da sia id che val.

+1

perché avrebbe bisogno di un indice su id quando sta cercando solo su val? – gbjbaanb

Problemi correlati