Recentemente descobri que o MySQL tem um mecanismo de "memória" que eu não conhecia (a maior parte do meu trabalho de banco de dados é para projetos de hobby, então aprendo o que preciso à medida que prossigo). Parece que essa opção deve me dar um desempenho drasticamente melhorado, então estou me perguntando se há alguma desvantagem relacionada a ela. Os dois que eu conheço são:
- Eu preciso ter memória RAM suficiente para manter a(s) tabela(s) em questão.
- As tabelas são perdidas se a máquina for desligada.
Acredito que o número 1 não deve ser um problema, pois estou usando o AWS EC2 e posso mudar para um tipo de instância com mais memória, se necessário. Acredito que posso mitigar o nº 2 despejando de volta no disco conforme necessário.
Que outras questões existem? O mecanismo de memória pode ter um desempenho pior do que o MyISAM ou o InnoDB? Acho que li algo que os índices são diferentes com este motor; isso é algo que eu preciso me preocupar?
Observando a lista de disponibilidade de recursos em http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html , dois possíveis problemas aparecem:
Fora isso, supondo que você tenha RAM suficiente, uma tabela baseada em memória deve ser mais rápida que uma baseada em disco. Obviamente, você precisa levar em consideração a captura de instantâneos em disco para resolver o problema do que acontece quando a instância do servidor é redefinida, o que provavelmente anulará completamente o benefício geral de desempenho se os dados precisarem ser capturados com frequência (se você puder viver perdendo um dia de dados em tal instância, você poderia fazer um backup uma vez por dia, mas na maioria dos casos isso não seria aceitável).
Uma alternativa pode ser:
SELECT * FROM <table> ORDER BY <pkey fields>
para cada tabela seguido deSELECT <indexed fields> FROM <table> ORDER BY <index fields>
para cada índiceDessa forma, todos os seus dados estão na RAM, você só precisa se preocupar com o desempenho de E/S para operações de gravação. Se o conjunto de trabalho comum do seu aplicativo for muito menor do que todo o banco de dados (o que geralmente é o caso - na maioria dos aplicativos, a maioria dos usuários estará olhando apenas os dados mais recentes na maior parte do tempo), talvez seja melhor ser mais seletivo sobre quanto você digitaliza para pré-carregar na memória, permitindo que o restante seja carregado do disco sob demanda.
Existem muitos casos para não usar o mecanismo de armazenamento de memória - e quando o InnoDB será mais rápido. Você só precisa pensar em simultaneidade e não em testes triviais de thread único.
Se você tiver um buffer pool grande o suficiente, o InnoDB se tornará inteiramente residente na memória para operações de leitura também. Os bancos de dados têm caches . Eles se aquecem!
Além disso - não subestime o valor do bloqueio em nível de linha e MVCC (os leitores não bloqueiam os gravadores). Pode ser "mais lento" quando as gravações precisam persistir no disco. Mas pelo menos você não estará bloqueando durante essa operação de gravação como estaria em uma tabela de memória (sem MVCC; bloqueio no nível da tabela).
Para o registro. Testei tabelas Mysql na memória para armazenar algumas informações. E testei o APC do PHP (APCu) para armazenar as mesmas informações.
Para 58.000 registros. (varchar + inteiro + data).
A tabela tem apenas um único índice, então não acho que seja o fator principal.
Conclusão:
A tabela de memória não é uma opção para tabelas "grandes" porque usa muita memória.
A outra desvantagem das tabelas baseadas em MEMORY é que elas não podem ser referenciadas várias vezes na mesma consulta. Pelo menos esse comportamento foi encontrado até a v5.4. Como com CTEs (desde v8.x) não há necessidade de usar tabelas intermediárias baseadas em mem para procedimentos complexos.
De acordo com os manuais do MySQL e do MariaDB, BLOB e CLOB (vários tipos de TEXT) não são suportados pelo armazenamento MEMORY. Para nossos próprios propósitos, isso tornou o mecanismo de armazenamento MEMORY quase inútil.
http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html
https://mariadb.com/kb/en/mariadb/memory-storage-engine/
Ao tentar converter apenas parte do banco de dados em armazenamento de MEMÓRIA, descobri que as chaves estrangeiras do mecanismo entre armazenamentos não são suportadas. Portanto, todas as tabelas, que devem ter referências de chave estrangeira para as tabelas, contendo BLOB/CLOB também devem estar em tipos de armazenamento sem memória (pelo menos, isso afeta as tabelas filhas do InnoDB).
As tabelas MEMORY não se destinam ao armazenamento persistente, principalmente de grandes subconjuntos de dados ou qualquer coisa em que a retenção seja crítica. A melhor finalidade deles, com base na minha experiência, é hospedar registros transitórios durante a criação e o preenchimento de tabelas temporárias durante procedimentos complexos, o que é significativamente mais rápido do que a maioria dos outros tipos de tabelas para essa finalidade, desde que o limite de buffer de chave para o mecanismo seja definido alto o suficiente para não ocorrer uma gravação em disco. Isso pode operar uma ordem de magnitude mais rápida que o MyISAM ou InnoDB para esse propósito, pois não há E/S de disco e, no caso de uma tabela encapsulada em um procedimento específico, a indexação e as relações não têm tanto significado quanto seria onde a persistência é esperada.
Além das respostas anteriores. direto do manual do MySQL 5.7:
"O desempenho de MEMORY é limitado pela contenção resultante da execução de thread único e sobrecarga de bloqueio de tabela ao processar atualizações. Isso limita a escalabilidade quando a carga aumenta, principalmente para combinações de instruções que incluem gravações."
...e esta é uma limitação muito real. Por exemplo: quando você tem várias sessões tentando criar tabelas temporárias de MEMORY rápidas, o single-threading pode causar um sério gargalo de desempenho.