MyISAM contro InnoDB [chiuso]


857

Sto lavorando a un progetto che coinvolge molte scritture di database, direi ( 70% di inserti e 30% di letture ). Questo rapporto includerebbe anche gli aggiornamenti che considero una lettura e una scrittura. Le letture possono essere sporche (ad esempio non ho bisogno di informazioni accurate al 100% al momento della lettura).
L'attività in questione eseguirà oltre 1 milione di transazioni di database all'ora.

Ho letto un sacco di cose sul web sulle differenze tra MyISAM e InnoDB e MyISAM mi sembra la scelta ovvia per il particolare database / tabelle che userò per questo compito. Da quello che mi sembra di leggere, InnoDB è utile se sono necessarie transazioni poiché è supportato il blocco a livello di riga.

Qualcuno ha qualche esperienza con questo tipo di carico (o superiore)? MyISAM è la strada da percorrere?


13
Il blog sulle prestazioni di MySQL è un'ottima risorsa per questo tipo di cose.
Ceejayoz,

3
Ciò dipenderebbe un po 'dal fatto che il tuo sistema sia OLTP o più orientato al datawarehouse (dove la maggior parte delle scritture sta caricando in massa).
nn.

35
MyISAM non supporta il blocco delle righe, le transazioni, non supporta nemmeno le chiavi esterne ... diavolo, dal momento che non può fornire ACID , non può nemmeno essere considerato un database corretto! Questo è il motivo per cui InnoDB è il motore predefinito da MySQL 5.5 ... ma, per qualsiasi motivo, MyISAM continua ad essere il motore predefinito per le tabelle create in PhpMyAdmin, quindi molti database amatoriali da quando sono stati eseguiti su MyISAM.
BlueRaja - Danny Pflughoeft,


Risposte:


523

Ho discusso brevemente questa domanda in una tabella in modo da poter concludere se andare con InnoDB o MyISAM .

Ecco una piccola panoramica di quale motore di archiviazione db dovresti usare in quale situazione:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Ricerca full-text richiesta Sì 5.6.4
-------------------------------------------------- --------------
Richiedi transazioni Sì
-------------------------------------------------- --------------
Domande frequenti sulla selezione Sì      
-------------------------------------------------- --------------
Inserimento, aggiornamento, eliminazione frequenti Sì
-------------------------------------------------- --------------
Blocco riga (elaborazione multipla su tabella singola) Sì
-------------------------------------------------- --------------
Progetto di base relazionale Sì

Sommario

  • In quasi tutte le circostanze, InnoDB è il modo migliore di procedere
  • Ma, lettura frequente, quasi nessuna scrittura, usa MyISAM
  • Ricerca full-text in MySQL <= 5.5, utilizzare MyISAM

11
InnoDB ha indici full-text in MySQL 5.6, ma finora non sono davvero pronti per l'uso in produzione.
Bill Karwin,

3
Accordo con 12.9. Funzioni di ricerca full-text , "Gli indici full-text possono essere utilizzati solo con tabelle InnoDB o MyISAM". Sembra OK per MySQL> = 5.6, tuttavia la stessa pagina per MySQL 5.5, dice ancora "Gli indici full-text possono essere utilizzati solo con le tabelle MyISAM". La tabella sopra potrebbe essere aggiornata per indicare come differisce con le versioni di MySQL. Sfortunatamente, finora, MySQL 5.5 sembra essere lo standard.
Hibou57,

2
Che cosa è media di: InnoDB - full-text: 5.6.4?? È sì o no?

2
MyISAM memorizza anche il conteggio delle righe internamente. Pertanto, la funzione Count () è quasi gratuita in MyISAM, mentre in InnoDB ci vuole molto tempo.
Hedeshy,

3
buon tavolo, ma aggiungendo una riga per qualità e stabilità, MyIsam = no, innoDB = yes lo renderebbe ancora migliore
pilavdzice

268

Non sono un esperto di database e non parlo per esperienza. Però:

Le tabelle MyISAM utilizzano il blocco a livello di tabella . In base alle stime del traffico, hai quasi 200 scritture al secondo. Con MyISAM, solo uno di questi potrebbe essere in corso in qualsiasi momento . Devi assicurarti che il tuo hardware possa tenere il passo con queste transazioni per evitare di essere sovraccaricato, cioè una singola query non può richiedere più di 5ms.

Ciò mi suggerisce che avresti bisogno di un motore di archiviazione che supporti il ​​blocco a livello di riga, ovvero InnoDB.

D'altra parte, dovrebbe essere abbastanza banale scrivere alcuni semplici script per simulare il carico con ciascun motore di archiviazione, quindi confrontare i risultati.


12
Quasi 200? Se la sua transazione media fa 2,5 query, questo è [(2.5 * 1M) / 3600s =] più vicino a 700.
Ozzy,

12
Non sono d'accordo anche a single query can take no more than 5msperché hai fatto 2 ipotesi improbabili; A: tutte le query necessitavano della stessa tabella e B: c'era solo 1 connessione disponibile! Dovrei informarti che un setup Linux e MySQL 5.5 con RAM elevata può supportare fino a 10.000 connessioni simultanee (Vedi: dev.mysql.com/doc/refman//5.5/it/too-many-connections.html )
Ozzy,

152
Quando una tabella è bloccata, è possibile eseguire solo una query alla volta. Non importa se il server supporta 10000 connessioni simultanee, ognuna eseguirà il backup mentre la tabella è bloccata.
Ryaner,

2
Inoltre potrebbe essere utile sapere che MyISAM supporta l'indice spaziale mentre InnoDB no. E MyISAM non sembra usare chiavi esterne anche se non impedisce di crearne una.
Kriver,

4
@kriver: non puoi avere chiavi esterne nelle tabelle MyISAM. È possibile includere le definizioni FK nelle istruzioni CREATE TABLE ma esse (le definizioni) vengono semplicemente ignorate.
ypercubeᵀᴹ

191

Le persone spesso parlano di prestazioni, letture vs. scritture, chiavi esterne, ecc. Ma secondo me c'è un'altra caratteristica indispensabile per un motore di archiviazione: gli aggiornamenti atomici.

Prova questo:

  1. Emettere un AGGIORNAMENTO sulla tabella MyISAM che richiede 5 secondi.
  2. Mentre l'AGGIORNAMENTO è in corso, dire 2,5 secondi in, premere Ctrl-C per interromperlo.
  3. Osserva gli effetti sul tavolo. Quante righe sono state aggiornate? Quanti non sono stati aggiornati? La tabella è persino leggibile o è stata danneggiata quando si preme Ctrl-C?
  4. Prova lo stesso esperimento con UPDATE su una tabella InnoDB, interrompendo la query in corso.
  5. Osservare la tabella InnoDB. Zero righe sono state aggiornate. InnoDB ha assicurato la presenza di aggiornamenti atomici e, se non è possibile eseguire il commit dell'aggiornamento completo, ripristina l'intera modifica. Inoltre, la tabella non è danneggiata. Funziona anche se si utilizza killall -9 mysqldper simulare un arresto anomalo.

Le prestazioni sono ovviamente auspicabili, ma non perdere i dati dovrebbe prevalere.


4
Per la cronaca, anche le altre caratteristiche di un database ACID - Coerenza, Isolamento e Durabilità - non sono supportate da MyISAM.
Bill Karwin,

Control-C non dovrebbe corrompere la tabella - come in CHECK TABLE restituirà il successo e tutte le query procederanno senza errori. MyISAM interromperà l'aggiornamento senza aggiornare tutti i record, ma la tabella manterrà l'integrità strutturale interna. Uccidere mysqld con SIGTERM avrà lo stesso effetto. Tuttavia, se gli dai SIGKILL (uccidi -9) o qualche segnale di crash (o lo guadagna da solo quando colpisce un bug), o se il sistema operativo si arresta in modo anomalo / si perde energia, allora è una storia diversa - puoi vedere Corruzione a livello di MyISAM.
Sasha Pachev,

1
Anche InnoDB può corrompersi in modo regale, di solito più regale di MyISAM quando lo fa. L'ironia di ACID è che abbiamo la nozione di tutto o niente. Quindi, quando InnoDB non può dare tutto, non dà nulla - asserzione interna, e si rifiuta di funzionare perché un byte in una struttura è errato - il 90% delle volte avrebbe potuto essere ignorato e avrebbe influenzato al massimo solo una tabella. I server Percona recenti hanno la possibilità di gestirlo - innodb_pass_corrupt_table.
Sasha Pachev,

1
Stavo cercando questo tipo di informazioni negli ultimi 3 giorni, ora ho capito. InnoDB è il migliore. GrazieBill Karwin
user3833682

3
@ flow2k, quasi nessuno, in questi giorni. Nel mio ultimo lavoro abbiamo usato MyISAM per una tabella su un server e l'unica ragione era che MyISAM era in grado di memorizzare quella tabella specifica in meno spazio di quanto avrebbe fatto InnoDB. Eravamo limitati allo spazio su disco, quindi abbiamo dovuto utilizzare MyISAM fino a quando non abbiamo potuto spostare il database su un altro server. Nel mio nuovo lavoro, esiste già una politica secondo cui ogni tabella deve essere InnoDB.
Bill Karwin,

138

Ho lavorato su un sistema ad alto volume usando MySQL e ho provato sia MyISAM che InnoDB.

Ho scoperto che il blocco a livello di tabella in MyISAM ha causato seri problemi di prestazioni per il nostro carico di lavoro che sembra simile al tuo. Purtroppo ho anche scoperto che le prestazioni con InnoDB erano anche peggiori di quanto sperassi.

Alla fine ho risolto il problema della contesa frammentando i dati in modo tale che gli inserti andassero in una tabella "calda" e selezionassero mai la query della tavola calda.

Ciò ha anche permesso di eliminare (i dati erano sensibili al tempo e abbiamo conservato solo X giorni) su tabelle "obsolete" che non sono state nuovamente toccate da query selezionate. InnoDB sembra avere scarse prestazioni sulle eliminazioni di massa, quindi se stai pianificando di eliminare i dati potresti voler strutturarli in modo tale che i vecchi dati si trovino in una tabella non aggiornata che può essere semplicemente eliminata invece di eseguirne le eliminazioni.

Ovviamente non ho idea di quale sia la tua applicazione, ma spero che questo ti dia un'idea di alcuni dei problemi con MyISAM e InnoDB.


3
"Alla fine ho risolto il problema della contesa frammentando i dati in modo tale che gli inserti andassero in una tabella" calda "e non selezionassero mai la tabella calda". - Non è essenzialmente ciò a cui serve un pool di buffer ?
BlueRaja - Danny Pflughoeft

15
Danny - No, non proprio. L'ottimizzazione delle impostazioni del server è importante, ma non sostituisce in alcun modo la strutturazione ponderata dello schema. Se si dispone di un DB molto, molto più grande della RAM disponibile e dei modelli di accesso che toccano i dati in modo casuale in tutto il DB, allora tutte le regolazioni del pool di buffer nel mondo non ti aiuteranno. Se capisci i dati e i modelli di accesso, puoi attenuare gran parte del dolore attraverso un'attenta progettazione.
alanc10n

66

Un po 'in ritardo al gioco ... ma ecco un post abbastanza completo che ho scritto qualche mese fa , descrivendo in dettaglio le principali differenze tra MYISAM e InnoDB. Prendi una tazza (e forse un biscotto) e divertiti.


La principale differenza tra MyISAM e InnoDB sta nell'integrità referenziale e nelle transazioni. Esistono anche altre differenze come blocco, rollback e ricerche full-text.

Integrità referenziale

L'integrità referenziale garantisce che le relazioni tra le tabelle rimangano coerenti. Più specificamente, ciò significa che quando una tabella (ad es. Schede) ha una chiave esterna (ad es. ID prodotto) che punta a una tabella diversa (ad es. Prodotti), quando si verificano aggiornamenti o eliminazioni alla tabella puntata, queste modifiche vengono messe in cascata al collegamento tavolo. Nel nostro esempio, se un prodotto viene rinominato, anche le chiavi esterne della tabella di collegamento verranno aggiornate; se un prodotto viene eliminato dalla tabella "Prodotti", verranno eliminati anche tutti gli elenchi che puntano alla voce eliminata. Inoltre, ogni nuovo elenco deve avere quella chiave esterna che punta a una voce valida ed esistente.

InnoDB è un DBMS relazionale (RDBMS) e quindi ha integrità referenziale, mentre MyISAM no.

Transazioni e atomicità

I dati in una tabella sono gestiti usando le istruzioni DML (Data Manipulation Language), come SELECT, INSERT, UPDATE e DELETE. Una transazione raggruppa due o più istruzioni DML insieme in una singola unità di lavoro, quindi viene applicata l'intera unità o nessuna di esse.

MyISAM non supporta le transazioni mentre InnoDB lo fa.

Se un'operazione viene interrotta durante l'utilizzo di una tabella MyISAM, l'operazione viene immediatamente interrotta e le righe (o anche i dati all'interno di ciascuna riga) interessate rimangono interessate, anche se l'operazione non è stata completata.

Se un'operazione viene interrotta durante l'utilizzo di una tabella InnoDB, poiché utilizza transazioni con atomicità, tutte le transazioni che non sono state completate non avranno effetto, poiché non viene eseguito alcun commit.

Blocco tabella vs Blocco riga

Quando una query viene eseguita su una tabella MyISAM, l'intera tabella in cui viene eseguita la query verrà bloccata. Ciò significa che le query successive verranno eseguite solo al termine di quella corrente. Se stai leggendo una tabella di grandi dimensioni e / o ci sono frequenti operazioni di lettura e scrittura, questo può significare un enorme arretrato di query.

Quando una query viene eseguita su una tabella InnoDB, vengono bloccate solo le righe interessate, il resto della tabella rimane disponibile per le operazioni CRUD. Ciò significa che le query possono essere eseguite contemporaneamente sulla stessa tabella, purché non utilizzino la stessa riga.

Questa funzione in InnoDB è nota come concorrenza. Per quanto la concorrenza sia, c'è un grosso svantaggio che si applica a un intervallo selezionato di tabelle, in quanto vi è un sovraccarico nel passaggio tra i thread del kernel e si dovrebbe impostare un limite sui thread del kernel per evitare che il server si fermi .

Transazioni e rollback

Quando si esegue un'operazione in MyISAM, le modifiche vengono impostate; in InnoDB, è possibile ripristinare tali modifiche. I comandi più comuni utilizzati per controllare le transazioni sono COMMIT, ROLLBACK e SAVEPOINT. 1. COMMIT: è possibile scrivere più operazioni DML, ma le modifiche verranno salvate solo quando viene effettuato un COMMIT 2. ROLLBACK: è possibile scartare qualsiasi operazione non ancora impegnata 3. SAVEPOINT: imposta un punto nell'elenco di operazioni a cui è possibile eseguire il rollback di un'operazione ROLLBACK

Affidabilità

MyISAM non offre integrità dei dati: guasti hardware, arresti non puliti e operazioni annullate possono causare la corruzione dei dati. Ciò richiederebbe la riparazione o la ricostruzione completa degli indici e delle tabelle.

InnoDB, d'altra parte, utilizza un registro transazionale, un buffer a doppia scrittura e checksum e validazione automatici per prevenire la corruzione. Prima che InnoDB apporti delle modifiche, registra i dati prima delle transazioni in un file di tablespace di sistema chiamato ibdata1. In caso di arresto anomalo, InnoDB eseguirà il ripristino automatico tramite la riproduzione di tali registri.

Indicizzazione FULLTEXT

InnoDB non supporta l'indicizzazione FULLTEXT fino a MySQL versione 5.6.4. Al momento della stesura di questo post, la versione MySQL di molti provider di hosting condiviso è ancora al di sotto della 5.6.4, il che significa che l'indicizzazione FULLTEXT non è supportata per le tabelle InnoDB.

Tuttavia, questo non è un motivo valido per utilizzare MyISAM. È meglio passare a un provider di hosting che supporti le versioni aggiornate di MySQL. Non che una tabella MyISAM che utilizza l'indicizzazione FULLTEXT non possa essere convertita in una tabella InnoDB.

Conclusione

In conclusione, InnoDB dovrebbe essere il motore di archiviazione predefinito scelto. Scegli MyISAM o altri tipi di dati quando soddisfano un'esigenza specifica.


Stavo realizzando uno script di checksum della sessione php e la maggior parte delle mie chiavi sono stringhe casuali di [az09] ... Innodb ha impiegato più di 30ms per fare un INSERT ON DUPLICATE KEY UPDATEcosì quindi ho provato MyISAM e ora è <1ms ... Molte risposte che ho visto dicono che innodb ha difficoltà a gestire chiavi univoche "inattendibili" (stringa casuale) ... Hai qualche input per noi al riguardo? In effetti, mi chiedevo quale impatto avrebbe dovuto usare MyISAM, ma la tua grande risposta mi ha fatto capire che era la strada da percorrere per quel caso particolare.
Louis Loudog Trottier,

64

Per un carico con più scritture e letture, beneficerai di InnoDB. Poiché InnoDB offre il blocco delle righe anziché il blocco delle tabelle, i tuoi messaggi di posta SELECTelettronica possono essere simultanei, non solo tra loro ma anche con molti messaggi di posta INSERTelettronica. Tuttavia, a meno che non si intenda utilizzare le transazioni SQL, impostare InnoDB commit flush su 2 ( innodb_flush_log_at_trx_commit ). Questo ti restituisce molte prestazioni grezze che altrimenti perderesti quando sposti le tabelle da MyISAM a InnoDB.

Inoltre, considera l'aggiunta di replica. Questo ti dà un po 'di ridimensionamento della lettura e dato che hai dichiarato che le tue letture non devono essere aggiornate, puoi lasciare un po' indietro la replica. Basta essere sicuri che possa raggiungere qualsiasi cosa tranne il traffico più intenso o sarà sempre indietro e non raggiungerà mai. Se vai in questo modo, tuttavia, ti consiglio vivamente di isolare la lettura dagli slave e la gestione del ritardo di replica nel gestore del database. È molto più semplice se il codice dell'applicazione non lo sa.

Infine, prestare attenzione ai diversi carichi di tabella. Non avrai lo stesso rapporto di lettura / scrittura su tutte le tabelle. Alcuni tavoli più piccoli con letture vicine al 100% potrebbero permettersi di rimanere MyISAM. Allo stesso modo, se si dispone di alcune tabelle vicine al 100% in scrittura, è possibile trarne vantaggio INSERT DELAYED, ma questo è supportato solo in MyISAM (la DELAYEDclausola viene ignorata per una tabella InnoDB).

Ma benchmark per essere sicuri.


4
"InnoDB commit flush" ti riferisci innodb_flush_log_at_trx_commit?
Ceejayoz,

2
Ho trovato il tuo post molto utile, grazie. Attualmente valutare quando utilizzare MyISAM / InnoDB per i miei tavoli e il tuo post è stato utile. Saluti.
starmonkey,

2
Stati dev.mysql.com/doc/refman/5.5/en/insert-delayed.html : per le tabelle MyISAM, se non ci sono blocchi liberi nel mezzo del file di dati, sono supportate le istruzioni simultanee SELECT e INSERT. In queste circostanze, raramente è necessario utilizzare INSERTO RITARDATO con MyISAM.
tymtam,

Posta molto istruttiva. Ho avuto la stessa domanda dell'op e devo dire che il tuo post mi ha messo a mio agio sulla decisione del mio motore di database. Grazie! ++
Joe Majewski,

Nota rapida: il ritardo non è più supportato in 5.7. In alternativa, potresti voler provare con LOW_PRIORITY.
webmat,

59

Per aggiungere alla vasta selezione di risposte che coprono le differenze meccaniche tra i due motori, presento uno studio empirico di confronto della velocità.

In termini di pura velocità, non è sempre vero che MyISAM sia più veloce di InnoDB, ma nella mia esperienza tende ad essere più veloce per gli ambienti di lavoro PURE READ di un fattore di circa 2,0-2,5 volte. Chiaramente questo non è appropriato per tutti gli ambienti - come altri hanno scritto, MyISAM manca di cose come transazioni e chiavi esterne.

Ho fatto un po 'di benchmarking di seguito - ho usato Python per il looping e la libreria timeit per i confronti di temporizzazione. Per interesse ho anche incluso il motore di memoria, questo offre le migliori prestazioni su tutta la linea anche se è adatto solo per tavoli più piccoli (si incontrano continuamente The table 'tbl' is fullquando si supera il limite di memoria MySQL). I quattro tipi di selezione che guardo sono:

  1. SELEZIONI vaniglia
  2. conta
  3. SELECT condizionali
  4. sotto-selezioni indicizzate e non indicizzate

Innanzitutto, ho creato tre tabelle utilizzando il seguente SQL

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

con "MyISAM" ha sostituito "InnoDB" e "memoria" nella seconda e terza tabella.

 

1) Vanilla seleziona

Query: SELECT * FROM tbl WHERE index_col = xx

Risultato: pareggio

Confronto di vanilla seleziona da diversi motori di database

La velocità di questi è sostanzialmente la stessa e, come previsto, è lineare nel numero di colonne da selezionare. InnoDB sembra leggermente più veloce di MyISAM ma questo è davvero marginale.

Codice:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) conta

Query: SELECT count(*) FROM tbl

Risultato: MyISAM vince

Confronto dei conteggi da parte di diversi motori di database

Questo dimostra una grande differenza tra MyISAM e InnoDB - MyISAM (e memoria) tiene traccia del numero di record nella tabella, quindi questa transazione è veloce e O (1). La quantità di tempo necessaria per il conteggio di InnoDB aumenta in modo super-lineare con la dimensione della tabella nell'intervallo che ho studiato. Sospetto che molte delle accelerazioni delle query MyISAM osservate nella pratica siano dovute a effetti simili.

Codice:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) Seleziona condizionale

Query: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

Risultato: MyISAM vince

Confronto tra selezioni condizionali da diversi motori di database

In questo caso, MyISAM e la memoria si comportano all'incirca allo stesso modo e battono InnoDB di circa il 50% per tabelle più grandi. Questo è il tipo di query per cui i vantaggi di MyISAM sembrano essere massimizzati.

Codice:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) Sottoseleziona

Risultato: InnoDB vince

Per questa query, ho creato un set aggiuntivo di tabelle per la sottoselezione. Ciascuno è semplicemente due colonne di BIGINT, una con un indice di chiave primaria e una senza alcun indice. A causa delle grandi dimensioni della tabella, non ho testato il motore di memoria. Il comando di creazione della tabella SQL era

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

dove ancora una volta, "MyISAM" è sostituito da "InnoDB" nella seconda tabella.

In questa query, lascio la dimensione della tabella di selezione a 1000000 e invece variare la dimensione delle colonne selezionate.

Confronto di sotto-selezioni da diversi motori di database

Qui InnoDB vince facilmente. Dopo aver raggiunto una tabella di dimensioni ragionevoli, entrambi i motori si ridimensionano in modo lineare con le dimensioni della sottoselezione. L'indice accelera il comando MyISAM ma ha un effetto interessante sulla velocità di InnoDB. subSelect.png

Codice:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

Penso che il messaggio da portare a casa di tutto ciò sia che se sei veramente preoccupato per la velocità, devi confrontare le domande che stai facendo piuttosto che fare ipotesi su quale motore sarà più adatto.


1
le prestazioni non sono sempre l'unica considerazione, che ne dici di un grafico sulla stabilità? un motore non è adatto a nulla se si arresta in modo anomalo e non supporta le funzionalità di base del database.
pilavdzice,

1
MyISAM probabilmente batterebbe InnoDB la maggior parte delle volte se il my.cnffile non fosse ottimizzato per InnoDB. Non hai menzionato l' my.cnfaspetto del tuo file, che è davvero il fattore più importante per le prestazioni di InnoDB.
itoctopus

Grazie itoctopus - Mi piacerebbe saperne di più sulle ottimizzazioni che mi consigliate. Il codice completo utilizzato in questi test è sopra, sentiti libero di ripetere gli esperimenti con varie ottimizzazioni e facci sapere se trovi cambiamenti significativi nei risultati
StackG

32

Leggermente fuori tema, ma a fini di documentazione e completezza, vorrei aggiungere quanto segue.

In generale l'uso di InnoDB si tradurrà in un'applicazione MOLTO complessa, probabilmente anche più priva di bug. Poiché è possibile inserire tutta l'integrità referenziale (vincoli di chiave esterna) nel modello di dati, non è necessario un codice di applicazione simile a quello necessario con MyISAM.

Ogni volta che inserisci, elimini o sostituisci un record, DEVI controllare e mantenere le relazioni. Ad esempio, se si elimina un genitore, è necessario eliminare anche tutti i figli. Ad esempio, anche in un semplice sistema di blogging, se si elimina un record di post di blog, sarà necessario eliminare i record di commenti, i Mi piace, ecc. In InnoDB questo viene fatto automaticamente dal motore di database (se nel modello sono stati specificati i contrapposti ) e non richiede alcun codice applicazione. In MyISAM questo dovrà essere codificato nell'applicazione, il che è molto difficile nei web server. I server Web sono per natura molto simultanei / paralleli e poiché queste azioni dovrebbero essere atomiche e MyISAM non supporta transazioni reali, l'utilizzo di MyISAM per i server Web è rischioso / soggetto a errori.

Inoltre, nella maggior parte dei casi, InnoDB funzionerà molto meglio, per una serie di motivi, uno dei quali è in grado di utilizzare il blocco a livello di record rispetto al blocco a livello di tabella. Non solo in una situazione in cui le scritture sono più frequenti delle letture, anche in situazioni con join complessi su set di dati di grandi dimensioni. Abbiamo notato un aumento delle prestazioni di 3 volte solo usando le tabelle InnoDB sulle tabelle MyISAM per join molto grandi (impiegando diversi minuti).

Direi che in generale InnoDB (utilizzando un modello di dati 3NF completo di integrità referenziale) dovrebbe essere la scelta predefinita quando si utilizza MySQL. MyISAM deve essere utilizzato solo in casi molto specifici. Molto probabilmente funzionerà di meno, risultando in un'applicazione più grande e più buggy.

Avendo detto questo. Il datamodelling è un'arte che si trova raramente tra i webdesigner / programmatori. Senza offesa, ma spiega che MyISAM viene utilizzato così tanto.


31

InnoDB offre:

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

In InnoDB tutti i dati di fila, tranne TEXT e BLOB, possono occupare al massimo 8.000 byte. Non è disponibile l'indicizzazione di testo completo per InnoDB. In InnoDB i COUNT (*) s (quando WHERE, GROUP BY o JOIN non vengono utilizzati) vengono eseguiti più lentamente rispetto a MyISAM perché il conteggio delle righe non è memorizzato internamente. InnoDB memorizza sia i dati che gli indici in un unico file. InnoDB utilizza un pool di buffer per memorizzare nella cache dati e indici.

MyISAM offre:

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

MyISAM ha un blocco a livello di tabella, ma nessun blocco a livello di riga. Nessuna transazione Nessun recupero automatico degli arresti anomali, ma offre funzionalità di tabella di riparazione. Nessun vincolo di chiave esterna. Le tabelle MyISAM sono generalmente di dimensioni più compatte su disco rispetto alle tabelle InnoDB. Le tabelle MyISAM potrebbero essere ulteriormente ridotte di dimensioni comprimendo con myisampack se necessario, ma diventano di sola lettura. MyISAM memorizza gli indici in un file e i dati in un altro. MyISAM utilizza buffer di chiavi per la memorizzazione nella cache degli indici e lascia la gestione della cache dei dati al sistema operativo.

Nel complesso, consiglierei InnoDB per la maggior parte degli scopi e MyISAM solo per usi specializzati. InnoDB è ora il motore predefinito nelle nuove versioni di MySQL.


2
prima, VARCHAR in InnoDB può anche andare a pagine di overflow, come fanno BLOB e TEXT. Tutti questi tipi di dati sono archiviati in modo simile internamente.
Bill Karwin,

Buono a sapersi, @BillKarwin! Facciamo un forte uso di VARCHAR nella nostra app e far sì che VARCHAR contribuisca a questo limite di ~ 8kB era un po 'preoccupante.
Rinogo,


la risposta non è aggiornata annymore come motore innodb in MySQL versione 5.6+ al giorno d'oggi supporta anche l'indicizzazione di testo completo e anche MySQL 5.5 + / 5.7 + supporta tipi di dati spaziali (5.5+) e indici spaziali (r-tee) (5.7+) .. Per il miglior supporto occorrerebbe almeno avere MySQL versione 5.7+
Raymond Nijland

25

Se usi MyISAM, non eseguirai alcuna transazione all'ora, a meno che non consideri ogni istruzione DML come una transazione (che in ogni caso non sarà duratura o atomica in caso di crash).

Pertanto penso che tu debba usare InnoDB.

300 transazioni al secondo sembrano abbastanza. Se è assolutamente necessario che queste transazioni siano durature nel caso di mancanza di corrente, assicurarsi che il sottosistema I / O sia in grado di gestire facilmente così tante scritture al secondo. Sarà necessario almeno un controller RAID con cache alimentata a batteria.

Se riesci a fare un piccolo colpo di durabilità, puoi usare InnoDB con innodb_flush_log_at_trx_commit impostato su 0 o 2 (vedi i documenti per i dettagli), puoi migliorare le prestazioni.

Esistono numerose patch che possono aumentare la concorrenza di Google e di altre, queste possono essere interessanti se non riesci ancora a ottenere prestazioni sufficienti senza di esse.


24

La domanda e la maggior parte delle risposte non sono aggiornate .

Sì, è una vecchia storia di mogli che MyISAM è più veloce di InnoDB. notare la data della domanda: 2008; è ormai quasi un decennio più tardi. Da allora InnoDB ha fatto passi da gigante.

Il grafico drammatico era per il caso in cui vince MyISAM: COUNT(*) senza una WHEREclausola. Ma è davvero quello che passi il tempo a fare?

Se si esegue il test di concorrenza , è molto probabile che InnoDB vincerà, anche controMEMORY .

Se si esegue una scrittura durante il benchmarking SELECTs, MEMORYè probabile che MyISAM perda a causa del blocco a livello di tabella.

In effetti, Oracle è così sicuro che InnoDB è meglio di aver rimosso MyISAM da 8.0.

La domanda è stata scritta nei primi giorni del 5.1. Da allora, queste versioni principali sono state contrassegnate come "Disponibilità generale":

  • 2010: 5,5 (.8 a dicembre)
  • 2013: 5,6 (.10 di febbraio)
  • 2015: 5.7 (.9 in ottobre)
  • 2018: 8.0 (.11 in aprile)

In conclusione: non usare MyISAM


2
La tecnologia del database MySQL avanza. E StackOverflow domande e risposte rimangono impantanate in passato. Le principali differenze tra MyISAM e InnoDB riguardano meno il "caricamento" sul server e più il supporto per l' integrità e le transazioni referenziali , nonché la concorrenza e la recuperabilità (+10)
spencer7593,

12

Dai un'occhiata anche ad alcune sostituzioni drop-in per MySQL stesso:

MariaDB

http://mariadb.org/

MariaDB è un server di database che offre funzionalità di sostituzione drop-in per MySQL. MariaDB è realizzato da alcuni degli autori originali di MySQL, con l'assistenza della più ampia comunità di sviluppatori di software gratuiti e open source. Oltre alle funzionalità di base di MySQL, MariaDB offre una ricca serie di miglioramenti delle funzionalità, inclusi motori di archiviazione alternativi, ottimizzazioni dei server e patch.

Percona Server

https://launchpad.net/percona-server

Una sostituzione drop-in avanzata per MySQL, con prestazioni migliori, diagnostica migliorata e funzionalità aggiunte.


1
Li sto usando entrambi (Percona in produzione, Maria sullo sviluppo di windows). sono più veloci e funzionano perfettamente.
Moshe L

4
Questo non risponde alla domanda. MariaDB e Percona sono fork di MySQL e usano anche i motori InnoDB e MyISAM.
dr_11

12

Si prega di notare che la mia educazione formale e la mia esperienza sono con Oracle, mentre il mio lavoro con MySQL è stato interamente personale e nel mio tempo libero, quindi se dico cose vere per Oracle ma non vere per MySQL, mi scuso. Mentre i due sistemi condividono molto, la teoria relazionale / algebra è la stessa e i database relazionali sono ancora database relazionali, ci sono ancora molte differenze !!

Mi piace in particolare (oltre al blocco a livello di riga) che InnoDB sia basato su transazioni, il che significa che potresti aggiornare / inserire / creare / modificare / eliminare / ecc. Più volte per una "operazione" della tua applicazione web. Il problema che si pone è che se solo alcune di queste modifiche / operazioni finiscono per essere impegnate, ma altre no, la maggior parte delle volte (a seconda del design specifico del database) si finisce con un database con struttura / dati in conflitto.

Nota: con Oracle, le istruzioni create / alter / drop vengono chiamate istruzioni "DDL" (Data Definition) e attivano implicitamente un commit. Le istruzioni di inserimento / aggiornamento / eliminazione, denominate "DML" (manipolazione dei dati), non vengono impegnate automaticamente, ma solo quando viene eseguito un DDL, commit o exit / quit (o se si imposta la sessione su "commit automatico", oppure se il tuo client si auto-impegna). È indispensabile esserne consapevoli quando si lavora con Oracle, ma non sono sicuro di come MySQL gestisca i due tipi di affermazioni. Per questo motivo, voglio chiarire che non sono sicuro di questo quando si tratta di MySQL; solo con Oracle.

Un esempio di quando eccellono i motori basati su transazioni:

Supponiamo che io o te sia su una pagina Web per registrarsi per partecipare a un evento gratuito e uno degli scopi principali del sistema è consentire a un massimo di 100 persone di registrarsi, poiché questo è il limite dei posti a sedere per l'evento. Una volta raggiunte le 100 iscrizioni, il sistema disabiliterebbe ulteriori iscrizioni, almeno fino a quando gli altri non si annulleranno.

In questo caso, potrebbe esserci un tavolo per gli ospiti (nome, telefono, e-mail, ecc.) E un secondo tavolo che traccia il numero di ospiti che si sono registrati. Abbiamo quindi due operazioni per una "transazione". Supponiamo ora che dopo che le informazioni sull'ospite siano state aggiunte alla tabella GUESTS, ci sia una perdita di connessione o un errore con lo stesso impatto. La tabella GUESTS è stata aggiornata (inserita in), ma la connessione è stata persa prima di poter aggiornare i "posti disponibili".

Ora abbiamo un ospite aggiunto al tavolo degli ospiti, ma il numero di posti disponibili ora è errato (ad esempio, il valore è 85 quando è effettivamente 84).

Naturalmente ci sono molti modi per gestirlo, come tenere traccia dei posti disponibili con "100 meno il numero di righe nella tabella degli ospiti" o un codice che controlla che le informazioni siano coerenti, ecc. Ma con un database basato sulle transazioni motore come InnoDB, TUTTE le operazioni sono impegnate o NESSUNO di esse. Questo può essere utile in molti casi, ma come ho detto, non è l'UNICO modo per essere sicuri, no (un modo carino, tuttavia, gestito dal database, non dal programmatore / sceneggiatore).

Questo è tutto "basato sulle transazioni" significa essenzialmente in questo contesto, a meno che non mi manchi qualcosa - che l'intera transazione abbia successo come dovrebbe, o che nulla sia cambiato, dal momento che apportare solo modifiche parziali potrebbe fare un piccolo disturbo a SEVERE database, forse addirittura corrompendolo ...

Ma lo dirò ancora una volta, non è l'unico modo per evitare di fare casino. Ma è uno dei metodi che il motore stesso gestisce, lasciandoti al codice / script con solo la necessità di preoccuparti di "la transazione è andata a buon fine o no, e cosa devo fare in caso contrario (come riprovare)" invece di manualmente scrivere codice per verificarlo "manualmente" dall'esterno del database e fare molto più lavoro per tali eventi.

Infine, una nota sul blocco delle tabelle e sul blocco delle righe:

DICHIARAZIONE DI NON RESPONSABILITÀ: potrei sbagliarmi in tutto ciò che segue riguardo a MySQL e le situazioni ipotetiche / di esempio sono cose da esaminare, ma potrei sbagliarmi in ciò che è esattamente possibile causare corruzione con MySQL. Gli esempi sono tuttavia molto reali nella programmazione generale, anche se MySQL ha più meccanismi per evitare tali cose ...

Comunque, io sono abbastanza fiducioso in accordo con coloro che hanno sostenuto che il numero di connessioni sono ammessi in un momento non non lavorare intorno a un tavolo bloccato. In effetti, connessioni multiple sono l'intero punto di blocco di una tabella !! In modo che altri processi / utenti / app non siano in grado di corrompere il database apportando modifiche allo stesso tempo.

In che modo due o più connessioni che lavorano sulla stessa riga ti renderebbero UN GIORNO MALE? Supponiamo che ci siano due processi entrambi desiderino / debbano aggiornare lo stesso valore nella stessa riga, diciamo perché la riga è un record di un tour in autobus e ciascuno dei due processi desidera contemporaneamente aggiornare i "riders" o "available_seats" campo come "il valore corrente più 1."

Facciamo ipoteticamente, passo dopo passo:

  1. Il processo uno legge il valore corrente, diciamo che è vuoto, quindi '0' finora.
  2. Il processo due legge anche il valore corrente, che è ancora 0.
  3. Elabora una scrittura (corrente + 1) che è 1.
  4. Il processo due dovrebbe scrivere 2, ma poiché legge il valore corrente prima che il processo uno scriva il nuovo valore, anch'esso scrive 1 nella tabella.

Non sono sicuro che due connessioni potrebbero mescolarsi in quel modo, entrambi leggendo prima che il primo scriva ... Ma in caso contrario, vedrei ancora un problema con:

  1. Il processo uno legge il valore corrente, che è 0.
  2. Elabora una scrittura (corrente + 1), che è 1.
  3. Il processo due ora legge il valore corrente. Ma mentre elabora una DID write (update), non ha eseguito il commit dei dati, quindi solo quello stesso processo può leggere il nuovo valore che ha aggiornato, mentre tutti gli altri visualizzano il valore precedente, fino a quando non viene eseguito un commit.

Inoltre, almeno con i database Oracle, ci sono livelli di isolamento, che non perderò il nostro tempo nel tentativo di parafrasare. Ecco un buon articolo sull'argomento, e ogni livello di isolamento ha i suoi pro e contro, che andrebbe di pari passo con quanto importanti possano essere i motori basati sulle transazioni in un database ...

Infine, all'interno di MyISAM potrebbero esserci probabilmente diverse misure di salvaguardia, invece delle chiavi esterne e dell'interazione basata sulle transazioni. Beh, per esempio, v'è il fatto che un'intera tabella è bloccata, il che rende meno probabile che siano operazioni / FKS necessari .

E purtroppo, se sei a conoscenza di questi problemi di concorrenza, sì, puoi giocare in modo meno sicuro e scrivere semplicemente le tue applicazioni, impostare i tuoi sistemi in modo che tali errori non siano possibili (il tuo codice è quindi responsabile, piuttosto che il database stesso). Tuttavia, a mio avviso, direi che è sempre meglio utilizzare quante più garanzie possibili, programmare in modo difensivo ed essere sempre consapevoli che l'errore umano è impossibile da evitare completamente. Succede a tutti e chiunque affermi di essere immune da ciò deve mentire o non ha fatto altro che scrivere un'applicazione / script "Hello World". ;-)

Spero che ALCUNO sia utile a qualcuno, e ancora di più, spero di non essere stato solo un colpevole di ipotesi e di essere un umano in errore !! Mi scuso se è così, ma gli esempi sono buoni a cui pensare, ricercano il rischio e così via, anche se non sono potenziali in questo specifico contesto.

Sentiti libero di correggermi, modifica questa "risposta" e persino votala verso il basso. Per favore, prova a migliorare, piuttosto che correggere una mia cattiva ipotesi con un'altra. ;-)

Questa è la mia prima risposta, quindi ti prego di perdonare la lunghezza a causa di tutte le dichiarazioni di non responsabilità, ecc ... Non voglio sembrare arrogante quando non ne sono assolutamente certo!



5

Nella mia esperienza, MyISAM è stata una scelta migliore purché non si effettuino DELETE, AGGIORNAMENTI, un sacco di INSERT singoli, transazioni e indicizzazione full-text. A proposito, CHECK TABLE è orribile. Man mano che la tabella invecchia in termini di numero di righe, non sai quando finirà.


2
L'indicizzazione full-text è possibile solo con MyISAM, non con InnoDB.
Pixel Elephant,

2
@PixelElephant, che sta iniziando a cambiare in MySQL 5.6. InnoDB ha un tipo di indice full-text, ma finora non è pronto per l'uso in produzione IMHO.
Bill Karwin,

1
"L'indicizzazione full-text è possibile solo con MyISAM, non con InnoDB": non più vero da MySQL> = 5.6. Vedi dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57,

5

Ho capito che anche se Myisam ha una contesa bloccante, è ancora più veloce di InnoDb nella maggior parte degli scenari a causa dello schema di acquisizione a blocco rapido che utilizza. Ho provato più volte Innodb e ricado sempre su MyIsam per un motivo o per l'altro. Inoltre, InnoDB può richiedere molta CPU in caso di enormi carichi di scrittura.


4

Ogni applicazione ha il proprio profilo prestazionale per l'utilizzo di un database e è probabile che cambi nel tempo.

La cosa migliore che puoi fare è testare le tue opzioni. Il passaggio tra MyISAM e InnoDB è banale, quindi carica alcuni dati di test e lancia jmeter sul tuo sito e vedi cosa succede.


4

Ho provato a eseguire l'inserimento di dati casuali nelle tabelle MyISAM e InnoDB. Il risultato è stato piuttosto scioccante. MyISAM aveva bisogno di qualche secondo in meno per inserire 1 milione di righe rispetto a InnoDB per soli 10 mila!


2
Otterrai le stesse prestazioni se utilizzi la transazione e disattivi l'autocommit per il motore InnoDB.
Stanleyxu2005,

IDK ha le stesse prestazioni, ma è quello che faccio in applicatinos più complessi e lo accelera.
user965748,

1
Non hai fornito i dettagli esatti dell'esperimento: quali impostazioni di configurazione? Cosa c'era nelle tabelle prima? Che tipo di dati? e forse soprattutto, c'erano inserti sequenziali? Parallelo? Qual era il loro tempismo? Quanti core della CPU? Le discussioni? ecc.
einpoklum,

3

myisam è un NOGO per quel tipo di carico di lavoro (scritture ad alta concorrenza), non ho molta esperienza con innodb (testato 3 volte e trovato in ogni caso che le prestazioni hanno risucchiato, ma è passato un po 'di tempo dall'ultimo test) se tu non sei obbligato a eseguire mysql, considera di provare Postgres in quanto gestisce meglio le scritture simultanee MOLTO


3

In breve, InnoDB è utile se stai lavorando a qualcosa che necessita di un database affidabile in grado di gestire molte istruzioni INSERT e UPDATE.

e, MyISAM è buono se hai bisogno di un database che per lo più prenderà molte istruzioni di lettura (SELEZIONA) piuttosto che scrivere (INSERISCI e AGGIORNAMENTI), considerando il suo svantaggio sul blocco delle tabelle.

potresti voler dare un'occhiata;
Pro e contro di InnoDB
Pro e contro di MyISAM


2

So che questo non sarà popolare ma qui va:

myISAM non supporta gli elementi essenziali del database come le transazioni e l'integrità referenziale che spesso si traducono in applicazioni glitch / buggy. Non è possibile apprendere i fondamenti di progettazione del database corretti se non sono nemmeno supportati dal proprio motore di database.

Non usare l'integrità referenziale o le transazioni nel mondo del database è come non usare la programmazione orientata agli oggetti nel mondo del software.

InnoDB esiste ora, usalo invece! Perfino gli sviluppatori MySQL hanno finalmente concesso di cambiarlo nel motore predefinito nelle versioni più recenti, nonostante myISAM fosse il motore originale che era il default in tutti i sistemi legacy.

No, non importa se stai leggendo o scrivendo o quali considerazioni sulle prestazioni hai, l'utilizzo di myISAM può causare una varietà di problemi, come questo in cui mi sono appena imbattuto: stavo eseguendo una sincronizzazione del database e allo stesso tempo qualcun altro accesso a un'applicazione che ha avuto accesso a una tabella impostata su myISAM. A causa della mancanza di supporto per le transazioni e della scarsa affidabilità di questo motore, si è verificato un arresto anomalo dell'intero database e ho dovuto riavviare manualmente mysql!

Negli ultimi 15 anni di sviluppo ho usato molti database e motori. myISAM si è schiantato su di me circa una dozzina di volte durante questo periodo, altri database, solo una volta! E quello era un database Microsoft SQL in cui alcuni sviluppatori scrivevano un codice CLR difettoso (Common Language Runtime - fondamentalmente codice C # che viene eseguito all'interno del database), non era esattamente colpa del motore del database.

Sono d'accordo con le altre risposte qui che affermano che le applicazioni di alta disponibilità e prestazioni di alta qualità non dovrebbero usare myISAM in quanto non funzioneranno, non saranno abbastanza robuste o stabili da tradursi in un'esperienza senza frustrazione.Vedi la risposta di Bill Karwin per maggiori dettagli.

PS Devo amarlo quando i fan di myISAM effettuano il downvote ma non riesco a dirti quale parte di questa risposta sia errata.


5
non ho votato a fondo, ma se lo facessi sarebbe per un consiglio di non usare mai. la parola non dovrebbe mai essere cancellata nel vocabolario di uno sviluppatore ... essendo avvertimento "non dire mai mai".
Hubson Bropa,

1

Per quel rapporto di lettura / scrittura immagino che InnoDB funzionerà meglio. Dato che stai bene con letture sporche, potresti (se te lo permetti) replicare a uno schiavo e lasciare che tutte le tue letture vadano allo schiavo. Inoltre, considera l'inserimento in blocco, piuttosto che un record alla volta.


1

Quasi ogni volta che inizio un nuovo progetto, Google questa stessa domanda per vedere se trovo nuove risposte.

Alla fine si riduce a: prendo l'ultima versione di MySQL ed eseguo i test.

Ho delle tabelle in cui voglio fare ricerche chiave / valore ... e questo è tutto. Ho bisogno di ottenere il valore (0-512 byte) per una chiave hash. Non ci sono molte transazioni su questo DB. La tabella riceve aggiornamenti occasionalmente (nella sua interezza), ma 0 transazioni.

Quindi non stiamo parlando di un sistema complesso qui, stiamo parlando di una semplice ricerca, .. e di come (oltre a rendere residente la RAM della tabella) possiamo ottimizzare le prestazioni.

Faccio anche test su altri database (ad esempio NoSQL) per vedere se c'è un posto dove posso ottenere un vantaggio. Il più grande vantaggio che ho riscontrato è nella mappatura dei tasti, ma per quanto riguarda la ricerca, MyISAM li sta attualmente completando tutti.

Anche se, non eseguirei transazioni finanziarie con le tabelle MyISAM ma per ricerche semplici, dovresti provarlo .. in genere da 2 a 5 volte le query / sec.

Provalo, accolgo con favore il dibattito.


1

Se è il 70% di inserti e il 30% di letture, è più simile al lato InnoDB.


0

bottomline: se stai lavorando offline con selezioni su grandi blocchi di dati, MyISAM ti darà probabilmente velocità migliori (molto migliori).

ci sono alcune situazioni in cui MyISAM è infinitamente più efficiente di InnoDB: durante la manipolazione di grandi dump di dati offline (a causa del blocco delle tabelle).

esempio: stavo convertendo un file CSV (15 milioni di record) da NOAA che utilizza i campi VARCHAR come chiavi. InnoDB impiegava un'eternità, anche con grandi pezzi di memoria disponibili.

questo è un esempio del CSV (il primo e il terzo campo sono chiavi).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

poiché ciò che devo fare è eseguire un aggiornamento offline in batch dei fenomeni meteorologici osservati, utilizzo la tabella MyISAM per ricevere dati ed eseguo JOINS sulle chiavi in ​​modo da poter pulire il file in arrivo e sostituire i campi VARCHAR con chiavi INT (che sono correlate a tabelle esterne in cui sono memorizzati i valori originali VARCHAR).

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.