2010-07-22 15 views
6

Sto costruendo un database MySQL che contiene voci su sottostringhe speciali di DNA in specie di lievito. La mia tabella è simile a questa:COUNT e GROUP BY sui campi di testo sembra lento

+--------------+---------+------+-----+---------+-------+ 
| Field  | Type | Null | Key | Default | Extra | 
+--------------+---------+------+-----+---------+-------+ 
| species  | text | YES | MUL | NULL |  | 
| region  | text | YES | MUL | NULL |  | 
| gene   | text | YES | MUL | NULL |  | 
| startPos  | int(11) | YES |  | NULL |  | 
| repeatLength | int(11) | YES |  | NULL |  | 
| coreLength | int(11) | YES |  | NULL |  | 
| sequence  | text | YES | MUL | NULL |  | 
+--------------+---------+------+-----+---------+-------+ 

Ci sono circa 1,8 milioni di record. In un tipo di query voglio vedere quante sottostringhe DNA associate a ciascun tipo di specie e regione, in modo da emettere questo query:

select species, region, count(*) group by species, region; 

Le specie e le colonne regione avere solo due possibili voci (conservati/SCER per specie, e promotore/codifica per regione), ma questa query richiede circa 30 secondi.

È questo un normale periodo di attesa per questo tipo di query, date le dimensioni della tabella? È lento perché sto usando campi di testo invece di semplici valori interi o booleani (io preferisco i campi di testo come diversi ricercatori non CS useranno il DB). Altre idee e suggerimenti sarebbero benvenuti.

Si prega di scusa se questa è una domanda boneheaded, io sono un neofita SQL.

P.S. Ho anche visto this question ma la soluzione proposta non sembra rilevante per quello che sto facendo.

MODIFICA: La conversione di questi campi in VARCHAR ha ridotto il tempo di esecuzione a ~ 2,5 secondi. Nota, ho anche programmato la sincronizzazione con ENUM che ha avuto un tempismo simile.

+0

Quale campo è la tua chiave primaria? –

+0

Non ho una chiave primaria. Potrei farne artificialmente uno, ma sarebbe importante? – Rich

risposta

6

Perché tutte le colonne basate su stringhe sono definite come TEXT? Se leggi il confronto delle prestazioni, vedrai che TEXT era ~ 3 volte più lento di una colonna VARCHAR utilizzando l'indicizzazione identica: http://forums.mysql.com/read.php?24,105964,105964

+0

Buona cattura. Non ho notato che erano' text'. –

+0

Ho fatto TEXT perché un collega il mio ha detto che non ci sarebbe alcuna differenza tra questo e VARCHAR. :) L'uso di un VARCHAR ha portato il mio runtime da 33 secondi a 2.5 – Rich

+0

@Rich: Wow - non mi aspettavo una differenza così drammatica. ha cambiato le colonne delle specie e delle regioni in modo che fossero chiavi esterne per le tabelle con i rispettivi valori.Un INT è sempre 4 byte, mentre un VARCHAR (4) è 5, quindi puoi immaginare quanti byte VARCHAR (100) è. –

3

Se i tuoi campi avranno sempre solo 2 valori, farai molto meglio a renderli booleani. Dovresti anche creare tutto NOT NULL a meno che non ci sia un vero motivo per cui avrai bisogno che sia NULL.

Dai anche un'occhiata allo ENUM type per un modo migliore di utilizzare un numero finito di valori leggibili dall'uomo per una colonna.

Per quanto riguarda la lentezza, la prima cosa da provare è creare indici sulle colonne. Per la query particolare si sta mostrando qui, un indice su species, region dovrebbe fare una grande differenza:

create index on mytablename (species, region); 

dovrebbe farlo.

+2

Sei sicuro che l'indice farà un'enorme differenza con dati di cardinalità così bassi? –

+1

No, non ne sono sicuro, ma penso sia una buona ipotesi. Ho iniziato a scrivere alcuni sull'uso di 'EXPLAIN', ma ha iniziato a trasformarsi in una lattina di worm. E ho immaginato che il risultato finale sarebbe probabilmente che dovremmo provare a creare un indice comunque. – Vineet

+0

Ho provato l'indice, ma non ha fatto alcuna differenza. Ho anche provato VARCHAR come suggerito da OMG Ponies, che era molto più veloce. Dopo di che l'ho provato contro enum senza alcuna accelerazione notevole da parte di VARCHAR. – Rich