2012-03-30 19 views
8

Ho una tabella mysql con oltre 30 milioni di record che erano originariamente archiviati con myisam. Ecco una descrizione della tabella:Differenza di prestazioni tra Innodb e Myisam in Mysql

describe_table

avrei eseguire la seguente query su questa tabella che in genere dura circa 30 secondi per completare. Vorrei cambiare @eid ogni volta per evitare il caching del database o del disco.

select count(fact_data.id) 
    from fact_data 
    where [email protected] 
     and fact_data.metric_id=1 

ho poi convertito questa tabella di InnoDB senza apportare altri cambiamenti e in seguito la stessa query ora ritorna in meno di un secondo ogni volta che esegue la query. Anche quando imposto casualmente @eid per evitare il caching, la query ritorna in meno di un secondo.

Ho cercato le differenze tra i due tipi di archiviazione per cercare di spiegare il notevole miglioramento delle prestazioni ma non sono riuscito a trovare nulla. In effetti, molto di ciò che ho letto indica che Myisam dovrebbe essere più veloce.

Le query che sto eseguendo sono contro un database locale senza altri processi che colpiscono il database al momento dei test.

risposta

15

Questa è una differenza di prestazioni sorprendentemente ampia, ma posso pensare ad alcune cose che potrebbero contribuire.

MyISAM è stato storicamente considerato più veloce di InnoDB, ma per le versioni recenti di InnoDB, ciò è vero per un insieme di casi d'uso molto più ridotto. MyISAM è in genere più veloce per le scansioni di tabelle di tabelle di sola lettura. Nella maggior parte degli altri casi di utilizzo, in genere trovo InnoDB più veloce. Spesso molte volte più veloce. Le serrature da tavolo sono una campana a morto per MyISAM nella maggior parte del mio utilizzo di MySQL.

MyISAM memorizza nella cache gli indici nel buffer delle chiavi. Forse hai impostato il buffer della chiave troppo piccolo per poter effettivamente memorizzare nella cache l'indice per la tua tabella piuttosto grande.

MyISAM dipende dal sistema operativo per memorizzare nella cache i dati della tabella dai file .MYD nella cache del disco del sistema operativo. Se il sistema operativo sta esaurendo la memoria, inizierà a scaricare la cache del disco. Ciò potrebbe costringerlo a continuare a leggere dal disco.

InnoDB memorizza nella cache gli indici e i dati nel proprio buffer di memoria. Si può dire al sistema operativo di non usare anche la sua cache del disco se si imposta innodb_flush_method su O_DIRECT, sebbene questo non sia supportato su OS X.

InnoDB solitamente memorizza dati e indici in pagine 16kb. A seconda di come si modifica il valore di @eid tra le query, è possibile che siano già stati memorizzati nella cache i dati per una query a causa delle letture del disco di una query precedente.

Assicurarsi di aver creato gli indici in modo identico. Usa spiegare per verificare se MySQL sta usando l'indice. Dato che hai incluso l'output di descrivere invece di show create table o show index from, non posso dire se entity_id fa parte di un indice composito. Se non fosse la prima parte di un indice composito, non verrebbe utilizzata.

Se si utilizza una versione relativamente moderna di MySQL, eseguire il seguente comando prima di eseguire la query:

set profilatura = 1;

Ciò accenderà il profilo di query per la sessione. Dopo aver eseguito la query, eseguire

mostrare profili;

Questo vi mostrerà l'elenco di query per quali profili sono disponibili. Penso che mantenga gli ultimi 20 di default. Supponendo che la tua query sia stata la prima, esegui:

mostra profilo per la query 1;

Verrà quindi visualizzata la durata di ciascuna fase nell'esecuzione della query. Ciò è estremamente utile per determinare cosa (ad es. Blocchi delle tabelle, ordinamento, creazione di tabelle temporanee, ecc.) Causa un rallentamento della query.

6

Il mio primo sospetto sarebbe che la tabella originale MyISAM e/o gli indici diventassero frammentati nel tempo con conseguente rallentamento delle prestazioni. La tabella InnoDB non avrebbe lo stesso problema da quando è stata creata con tutti i dati già presenti in essa (quindi sarebbe stata memorizzata in modo sequenziale sul disco).

È possibile testare questa teoria ricostruendo la tabella MyISAM. Il modo più semplice per farlo sarebbe quello di utilizzare un "null" ALTER TABLE:

ALTER TABLE mytable ENGINE = MyISAM; 

quindi controllare le prestazioni per vedere se è meglio.

Un'altra possibilità potrebbe essere se il database stesso viene semplicemente ottimizzato per le prestazioni InnoDB anziché per MyISAM. Ad esempio, InnoDB utilizza lo innodb_buffer_pool_size parameter per sapere quanta memoria deve essere allocata per l'archiviazione di dati e indici memorizzati nella cache. Ma MyISAM utilizza il parametro key_buffer. Se il tuo database ha un grande pool di buffer innodb e un piccolo buffer di chiavi, le prestazioni di InnoDB saranno migliori delle prestazioni di MyISAM, specialmente per le tabelle di grandi dimensioni.

+0

Un test ragionevolmente semplice per la creazione di una nuova tabella MyISAM e il cronometraggio della query su tale tabella potrebbe confermare questa ipotesi. –

1

Quali sono le definizioni dell'indice, esistono modi in cui è possibile creare indici per MyISAM in cui i campi dell'indice non verranno utilizzati quando si pensa che lo faranno.

Problemi correlati