it-swarm.it

Quali sono i motivi ** NON ** per utilizzare il motore di archiviazione MEMORY in MySQL?

Recentemente ho scoperto che MySQL ha un motore di "memoria" di cui non ero a conoscenza (la maggior parte del mio lavoro di database è per progetti di hobbistica, quindi imparo ciò di cui ho bisogno mentre vado). Sembra che questa opzione dovrebbe darmi prestazioni drasticamente migliorate, quindi mi chiedo se ci siano degli svantaggi. I due che conosco sono:

  1. Ho bisogno di avere abbastanza RAM per contenere le tabelle in questione.
  2. Le tabelle vanno perse se la macchina si spegne.

Credo che il numero 1 non dovrebbe essere un problema dal momento che sto usando AWS EC2 e, se necessario, posso passare a un tipo di istanza con più memoria. Credo di poter mitigare il n. 2 scaricando di nuovo su disco secondo necessità.

Quali altri problemi ci sono? Il motore di memoria può mai offrire prestazioni peggiori di MyISAM o InnoDB? Penso di aver letto qualcosa che gli indici sono diversi con questo motore; è qualcosa di cui devo preoccuparmi?

30
Michael McGowan

Guardando l'elenco di disponibilità delle funzionalità su http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html due possibili problemi saltano fuori:

  1. Nessuna transazione o supporto FK, il che significa che dovrai gestire l'integrità transazionale e l'integrità referenziale nel tuo codice (che potrebbe finire per essere molto meno efficiente che lasciare che il DB faccia questo per te, anche se dipende molto dalla tua app modelli di comportamento previsti).
  2. Solo blocco a livello di tabella: questo potrebbe rappresentare un ostacolo significativo alla scalabilità se l'app richiede più writer simultanei sullo stesso set di tabelle o nei casi in cui le operazioni di lettura utilizzano i blocchi per garantire la lettura di dati coerenti, in questi casi una tabella basata su disco che supporta un blocco molto più preciso, la granularità funzionerà molto meglio se una quantità sufficiente del suo contenuto è attualmente memorizzata nella cache nella RAM.

A parte questo, supponendo che tu abbia abbastanza RAM, una tabella basata sulla memoria dovrebbe essere più veloce di una basata sul disco. Ovviamente è necessario considerare le istantanee su disco per risolvere il problema di ciò che accade quando viene ripristinata l'istanza del server, il che probabilmente annullerà completamente il vantaggio in termini di prestazioni nel caso in cui i dati debbano essere acquisiti spesso (se riesci a vivere perdendo un giorno di i dati in tal caso si potrebbe semplicemente fare un backup una volta al giorno, ma nella maggior parte dei casi ciò non sarebbe accettabile).

Un'alternativa potrebbe essere quella di:

  1. Utilizza le tabelle basate su disco, ma assicurati di avere più che sufficiente RAM per tenerle tutte in RAM in qualsiasi momento (e "RAM sufficiente" potrebbe essere più di quanto si pensi in quanto è necessario tenere conto di qualsiasi altro processo sulla macchina, OS IO buffer/cache e così via)
  2. Esegui la scansione dell'intero contenuto (tutti i dati e le pagine indice) della tabella su ogni avvio per precaricare il contenuto in memoria con SELECT * FROM <table> ORDER BY <pkey fields> per ogni tabella seguita da SELECT <indexed fields> FROM <table> ORDER BY <index fields> per ciascun indice

In questo modo tutti i tuoi dati sono nella RAM, devi solo preoccuparti delle prestazioni I/O per le operazioni di scrittura. Se il set di lavoro comune della tua app è molto più piccolo dell'intero DB (cosa che di solito accade - nella maggior parte delle applicazioni la maggior parte degli utenti guarderà i dati più recenti solo nel tempo) potresti essere meglio di essere più selettivo su quanto si esegue la scansione per precaricare in memoria, consentendo il resto da caricare su disco su richiesta.

27
David Spillett

Esistono molti casi per non utilizzare il motore di archiviazione della memoria e quando InnoDB sarà più veloce. Devi solo pensare alla concorrenza e non ai banali test a thread singolo.

Se si dispone di un pool buffer abbastanza grande, InnoDB diventerà interamente residente in memoria anche per le operazioni di lettura. I database hanno cache . Si riscaldano!

Inoltre, non sottovalutare il valore del blocco a livello di riga e MVCC (i lettori non bloccano gli scrittori). Potrebbe essere "più lento" quando le scritture devono persistere su disco. Ma almeno non ti blocchi durante quell'operazione di scrittura come se fossi su una tabella di memoria (nessun MVCC; blocco a livello di tabella).

15
Morgan Tocker

Per il record. Ho testato le tabelle Mysql in memoria per memorizzare alcune informazioni. E ho testato l'APC (APCu) di PHP per memorizzare le stesse informazioni.

Per 58000 registri. (varchar + intero + data).

  1. Informazioni originali 24mb in formato testo (formato csv).
  2. L'APC di PHP utilizza 44,7 MB di RAM.
  3. Mysql's Table utilizza 575 MB di RAM.

La tabella ha un solo indice quindi non penso che sia il fattore principale.

Conclusione:

La tabella di memoria è non un'opzione per le tabelle "grandi" perché utilizza troppa memoria.

3
magallanes

L'altro svantaggio delle tabelle basate su MEMORY è che non possono essere indirizzate più volte nella stessa query. Almeno quel comportamento è stato trovato fino alla v5.4. Come con i CTE (dalla v8.x) non è necessario utilizzare tabelle intermedie basate su mem per procedure complesse.

2
Kondybas

Oltre alle risposte precedenti. direttamente dal manuale di MySQL 5.7:

"Le prestazioni della MEMORIA sono limitate dalla contesa derivante dall'esecuzione a thread singolo e dal sovraccarico del blocco della tabella durante l'elaborazione degli aggiornamenti. Ciò limita la scalabilità quando aumenta il carico, in particolare per i mix di istruzioni che includono le scritture."

... e questa è una limitazione molto reale. Ad esempio: quando si hanno più sessioni che provano a creare tabelle temporanee MEMORY veloci e veloci, il single threading può causare seri colli di bottiglia nelle prestazioni.

1
Eljuan

Le tabelle MEMORY non sono intese per l'archiviazione persistente, in particolare di grandi sottoinsiemi di dati o di qualsiasi cosa in cui la conservazione è fondamentale. Il loro scopo migliore dalla mia esperienza è quello di ospitare registrazioni transitorie durante la creazione e il popolamento di tabelle temporanee durante procedure complesse, che si comporta in modo significativamente più veloce rispetto alla maggior parte degli altri tipi di tabella a questo scopo, a condizione che la soglia del buffer chiave per il motore sia impostata abbastanza in alto da non incorrere in una scrittura su disco. Questo può operare a un ordine di grandezza più veloce di MyISAM o InnoDB per questo scopo in quanto non vi è I/O del disco, e nel caso di una tabella che è incapsulata in una procedura specifica, l'indicizzazione e le relazioni non hanno tanto significato quanto loro dove sarebbe prevista la persistenza.

1
mopsyd

Secondo i manuali MySQL e MariaDB, BLOB e CLOB (vari tipi di TEXT) non sono supportati dalla memoria MEMORY. Per i nostri scopi, ciò ha reso quasi inutile il motore di archiviazione MEMORY.

http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html

Le tabelle MEMORY non possono contenere colonne BLOB o TEXT.

https://mariadb.com/kb/en/mariadb/memory-storage-engine/

Tipi di lunghezza variabile come VARCHAR possono essere utilizzati nelle tabelle MEMORY. Le colonne BLOB o TEXT non sono supportate per le tabelle MEMORY.

Quando ho provato a convertire solo una parte del database in memoria MEMORY, ho scoperto che le chiavi esterne del motore di archiviazione non sono supportate. Quindi, tutte le tabelle, che dovrebbero avere riferimenti a chiave esterna alle tabelle, contenenti BLOB/CLOB dovrebbero anche essere in tipi di memoria non di memoria (almeno, ciò influisce sulle tabelle figlio di InnoDB).

1
user2134886