Quais são os motivos para NÃO usar o mecanismo de armazenamento MEMORY no MySQL?
28
Recentemente, descobri que o MySQL tem um mecanismo de "memória" que eu não conhecia (a maior parte do meu trabalho com banco de dados é para projetos de hobby, então aprendo o que preciso à medida que vou). Parece que esta opção deve me proporcionar um desempenho drasticamente aprimorado, então estou me perguntando se há alguma desvantagem. Os dois que eu conheço são:
Preciso ter RAM suficiente para manter a (s) mesa (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 passar para um tipo de instância com mais memória, se necessário. Acredito que posso mitigar o número 2 ao voltar ao disco conforme necessário.
Que outras questões existem? O mecanismo de memória pode apresentar desempenho pior do que o MyISAM ou o InnoDB? Eu acho que li algo que os índices são diferentes com esse mecanismo; é com isso que eu preciso me preocupar?
Nenhuma transação ou suporte a FK, o que significa que você terá que gerenciar a integridade transacional e a integridade referencial em seu próprio código foram necessários (o que pode acabar sendo muito menos eficiente do que permitir que o banco de dados faça isso por você, embora isso dependa muito do aplicativo padrões de comportamento esperados).
Somente bloqueio no nível da tabela: isso pode ser uma barreira significativa à escalabilidade se o aplicativo precisar de vários gravadores simultâneos no mesmo conjunto de tabelas ou nos casos em que suas operações de leitura usem bloqueios para garantir a leitura de dados consistentes - nesses casos, uma tabela baseada em disco que suporta uma granularidade de bloqueio muito mais fina terá um desempenho muito melhor se o conteúdo suficiente estiver atualmente armazenado em cache na RAM.
Fora isso, supondo que você tenha RAM suficiente, uma tabela baseada em memória deve ser mais rápida que uma tabela baseada em disco. Obviamente, você precisa levar em consideração as capturas instantâneas em disco para resolver o problema do que acontece quando a instância do servidor é redefinida, o que provavelmente negará completamente o benefício geral de desempenho se os dados precisarem ser capturados com frequência (se você puder perder um dia de trabalho dados nesse caso, você pode fazer um backup apenas uma vez por dia, mas na maioria dos casos isso não seria aceitável).
Uma alternativa pode ser:
Use tabelas baseadas em disco, mas verifique se você possui RAM mais do que suficiente para mantê-las na RAM a qualquer momento (e "RAM suficiente" pode ser mais do que você pensa, pois precisa prestar contas de outros processos na máquina, SO Buffers de E / S / cache e assim por diante)
Digitalize todo o conteúdo (todos os dados e páginas de índice) da tabela em cada inicialização para pré-carregar o conteúdo na memória com SELECT * FROM <table> ORDER BY <pkey fields>cada tabela seguida por SELECT <indexed fields> FROM <table> ORDER BY <index fields>cada índice
Dessa 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 o banco de dados inteiro (o que geralmente acontece) - na maioria dos aplicativos, a maioria dos usuários só olha os dados mais recentes se houver tempo - é melhor você ser mais seletivo quanto a quanto você digitaliza para pré-carregar na memória, permitindo que o restante seja carregado do disco sob demanda.
Por que você precisaria de integridade transacional para um banco de dados na memória? Se a energia acabar, você está perdendo tudo de qualquer maneira.
Osa
@osa: supondo que ele permita acesso simultâneo em vez de serializar tudo, você precisará de alguma forma de gerenciamento de integridade para isso.
David Spillett
14
Existem muitos casos para não usar o mecanismo de armazenamento em memória - e quando o InnoDB será mais rápido. Você só precisa pensar em simultaneidade e não em testes simples de thread único.
Se você possui um buffer pool grande o suficiente, o InnoDB também se tornará residente na memória para operações de leitura. Bancos de dados têm caches . Eles se aquecem!
Além disso - não subestime o valor do bloqueio no nível da linha e do MVCC (os leitores não bloqueiam 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 se estivesse 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 eu testei o APC do PHP (APCu) para armazenar as mesmas informações.
Para 58000 registros. (varchar + inteiro + data).
Informação original 24mb em formato de texto (formato csv).
O APC do PHP usa 44,7mb de RAM.
A tabela do Mysql usa 575mb de RAM.
A tabela possui apenas um índice, então não acho que seja o fator principal.
Conclusão:
Tabela de memória não é uma opção para tabelas "grandes" porque usa muita memória.
Esta é uma resposta simplificada. O mecanismo de armazenamento MEMORY pode ser ajustado usando tipos de dados menores, definindo explicitamente o BTREE como o tipo de índice e limitando a quantidade de dados carregados na RAM. Ainda é uma opção viável para conjuntos menores. Também existem outros fatores, como E / S agressiva de disco. Veja minhas postagens dba.stackexchange.com/questions/6156/… e dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA 2/14
Na verdade, verifiquei a alteração do índice (e até a excluí-lo completamente) e o tamanho não mudou muito (incluindo uma reconstrução da tabela do zero). O IMHO Mysql está fazendo algo oculto, pode ser algum tipo de otimização ou alocação do maior tamanho por coluna (como em um varchar).
precisa saber é
6
O motivo é quase certamente devido ao seu VARCHAR: "MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length."dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html Efetivamente, parece que o VARCHAR se torna CHAR com o mecanismo MEMORY.
Matthew1471
2
A outra desvantagem das tabelas baseadas em MEMORY é que elas não podem ser referidas várias vezes na mesma consulta. Pelo menos esse comportamento foi encontrado até a v5.4. Como com CTEs (desde a v8.x) não há necessidade de usar tabelas intermediárias baseadas em mem para procedimentos complexos.
De acordo com os manuais MySQL e MariaDB, BLOB e CLOB (vários tipos de texto) não são suportados pelo armazenamento de MEMORY. Para nossos propósitos, isso tornou o mecanismo de armazenamento MEMORY quase inútil.
Tipos de comprimento variável, como VARCHAR, podem ser usados nas tabelas MEMORY. As colunas BLOB ou TEXT não são suportadas para tabelas MEMORY.
Ao tentar converter apenas parte do banco de dados em armazenamento MEMORY, 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 às tabelas contendo BLOB / CLOB também devem estar em tipos de armazenamento sem memória (pelo menos, isso afeta as tabelas filho do InnoDB).
As tabelas MEMORY não se destinam ao armazenamento persistente, particularmente de grandes subconjuntos de dados ou qualquer coisa em que a retenção seja crítica. O melhor objetivo da minha experiência é alojar registros transitórios durante a criação e o preenchimento de tabelas temporárias durante procedimentos complexos, com desempenho significativamente mais rápido do que a maioria dos outros tipos de tabela para esse fim, desde que o seu limite de buffer principal para o mecanismo seja alto o suficiente para não ocorrer uma gravação em disco. Isso pode operar uma ordem de magnitude mais rápido que o MyISAM ou o InnoDB para essa finalidade, 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 elas. seria onde persistência é esperada.
Além das respostas anteriores. direto do manual do MySQL 5.7:
"O desempenho da 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 misturas de instruções que incluem gravações."
... e essa é uma limitação muito real. Por exemplo: quando você tem várias sessões tentando criar boas e rápidas tabelas temporárias de MEMORY, o encadeamento único pode causar um sério gargalo de desempenho.
Existem muitos casos para não usar o mecanismo de armazenamento em memória - e quando o InnoDB será mais rápido. Você só precisa pensar em simultaneidade e não em testes simples de thread único.
Se você possui um buffer pool grande o suficiente, o InnoDB também se tornará residente na memória para operações de leitura. Bancos de dados têm caches . Eles se aquecem!
Além disso - não subestime o valor do bloqueio no nível da linha e do MVCC (os leitores não bloqueiam 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 se estivesse em uma tabela de memória (sem MVCC; bloqueio no nível da tabela).
fonte
Para o registro. Testei tabelas Mysql na memória para armazenar algumas informações. E eu testei o APC do PHP (APCu) para armazenar as mesmas informações.
Para 58000 registros. (varchar + inteiro + data).
A tabela possui apenas um índice, então não acho que seja o fator principal.
Conclusão:
Tabela de memória não é uma opção para tabelas "grandes" porque usa muita memória.
fonte
"MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length."
dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html Efetivamente, parece que o VARCHAR se torna CHAR com o mecanismo MEMORY.A outra desvantagem das tabelas baseadas em MEMORY é que elas não podem ser referidas várias vezes na mesma consulta. Pelo menos esse comportamento foi encontrado até a v5.4. Como com CTEs (desde a v8.x) não há necessidade de usar tabelas intermediárias baseadas em mem para procedimentos complexos.
fonte
De acordo com os manuais MySQL e MariaDB, BLOB e CLOB (vários tipos de texto) não são suportados pelo armazenamento de MEMORY. Para nossos 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 MEMORY, 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 às tabelas contendo BLOB / CLOB também devem estar em tipos de armazenamento sem memória (pelo menos, isso afeta as tabelas filho do InnoDB).
fonte
As tabelas MEMORY não se destinam ao armazenamento persistente, particularmente de grandes subconjuntos de dados ou qualquer coisa em que a retenção seja crítica. O melhor objetivo da minha experiência é alojar registros transitórios durante a criação e o preenchimento de tabelas temporárias durante procedimentos complexos, com desempenho significativamente mais rápido do que a maioria dos outros tipos de tabela para esse fim, desde que o seu limite de buffer principal para o mecanismo seja alto o suficiente para não ocorrer uma gravação em disco. Isso pode operar uma ordem de magnitude mais rápido que o MyISAM ou o InnoDB para essa finalidade, 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 elas. seria onde persistência é esperada.
fonte
Além das respostas anteriores. direto do manual do MySQL 5.7:
"O desempenho da 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 misturas de instruções que incluem gravações."
... e essa é uma limitação muito real. Por exemplo: quando você tem várias sessões tentando criar boas e rápidas tabelas temporárias de MEMORY, o encadeamento único pode causar um sério gargalo de desempenho.
fonte