MyISAM versus InnoDB [fechado]

857

Estou trabalhando em um projeto que envolve muitas gravações de banco de dados, eu diria ( inserções de 70% e leituras de 30% ). Essa proporção também incluiria atualizações que considero uma leitura e uma gravação. As leituras podem estar sujas (por exemplo, não preciso de informações 100% precisas no momento da leitura).
A tarefa em questão realizará mais de 1 milhão de transações de banco de dados por hora.

Eu li várias coisas na web sobre as diferenças entre o MyISAM e o InnoDB, e o MyISAM parece ser a escolha óbvia para mim para os bancos de dados / tabelas específicos que utilizarei para esta tarefa. Pelo que pareço estar lendo, o InnoDB é bom se forem necessárias transações, pois o bloqueio no nível de linha é suportado.

Alguém tem alguma experiência com esse tipo de carga (ou superior)? MyISAM é o caminho a percorrer?

user2013
fonte
13
O MySQL Performance Blog é um ótimo recurso para esse tipo de coisa.
ceejayoz
3
Isso dependeria um pouco se o seu sistema é OLTP ou mais orientado a datawarehouse (onde a maioria das gravações são carregadas em massa).
Nos
35
O MyISAM não suporta bloqueio de linhas, transações, nem suporta chaves estrangeiras ... inferno, uma vez que não pode fornecer ACID , dificilmente pode ser considerado um banco de dados adequado! É por isso que o InnoDB é o mecanismo padrão desde o MySQL 5.5 ... mas, por qualquer motivo, o MyISAM continua sendo o mecanismo padrão para as tabelas criadas no PhpMyAdmin, portanto, muitos bancos de dados amadores são executados no MyISAM.
precisa saber é o seguinte

Respostas:

523

Eu discuti brevemente essa questão em uma tabela para que você possa concluir se deseja usar o InnoDB ou o MyISAM .

Aqui está uma pequena visão geral de qual mecanismo de armazenamento db você deve usar em que situação:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Pesquisa de texto completo necessária Sim 5.6.4
-------------------------------------------------- --------------
Exigir transações Sim
-------------------------------------------------- --------------
Consultas frequentes de seleção Sim      
-------------------------------------------------- --------------
Inserção frequente, atualização, exclusão Sim
-------------------------------------------------- --------------
Bloqueio de linhas (multiprocessamento em tabela única) Sim
-------------------------------------------------- --------------
Design de base relacional Sim

Sumário

  • Em quase todas as circunstâncias, o InnoDB é o melhor caminho a percorrer
  • Mas, leitura frequente, quase sem escrita, use o MyISAM
  • Pesquisa de texto completo no MySQL <= 5.5, use MyISAM
developer99
fonte
11
O InnoDB possui índices de texto completo no MySQL 5.6, mas até agora, eles não estão realmente prontos para uso em produção.
Bill Karwin
3
Acordo com 12.9. Funções de pesquisa de texto completo , “Índices de texto completo podem ser usados ​​apenas com tabelas InnoDB ou MyISAM”. Parece OK para o MySQL> = 5.6, porém a mesma página para o MySQL 5.5, ainda diz “Índices de texto completo podem ser usados ​​apenas com tabelas MyISAM”. A tabela acima pode ser atualizada para dizer como difere das versões do MySQL. Infelizmente, até agora, o MySQL 5.5 parece ser o padrão.
precisa saber é o seguinte
2
O que significa: InnoDB - full-text: 5.6.4?? É sim ou não?
2
O MyISAM também armazena a contagem de linhas internamente. Portanto, a função Count () é quase gratuita no MyISAM, enquanto que o InnoDB demora bastante tempo.
Hedeshy
3
boa mesa, mas a adição de uma linha para a qualidade e estabilidade, myisam = no, innoDB = yes tornaria ainda melhor
pilavdzice
268

Não sou especialista em banco de dados e não falo por experiência própria. Contudo:

As tabelas MyISAM usam bloqueio no nível da tabela . Com base nas suas estimativas de tráfego, você tem cerca de 200 gravações por segundo. Com o MyISAM, apenas um deles pode estar em andamento a qualquer momento . Você precisa garantir que seu hardware possa acompanhar essas transações para evitar a sobrecarga, ou seja, uma única consulta não pode demorar mais que 5 ms.

Isso sugere que você precisaria de um mecanismo de armazenamento que suporte o bloqueio no nível da linha, ou seja, o InnoDB.

Por outro lado, deve ser bastante trivial escrever alguns scripts simples para simular a carga com cada mecanismo de armazenamento e comparar os resultados.

rix0rrr
fonte
12
Perto de 200? Se a transação média dele fizer 2,5 consultas, isso é [(2,5 * 1M) / 3600s =] mais próximo de 700. #
Ozzy
12
Também não concordo a single query can take no more than 5msporque você fez duas suposições improváveis; R: todas as consultas precisavam da mesma tabela & B: havia apenas 1 conexão disponível! Devo informar que uma configuração Linux e MySQL 5.5 com alta RAM pode suportar até 10.000 conexões simultâneas (consulte dev.mysql.com/doc/refman//5.5/en/too-many-connections.html )
amigos estão
152
Quando uma tabela está bloqueada, apenas uma consulta pode ser executada por vez. Não importa se o servidor suporta 10000 conexões simultâneas, cada um fará backup enquanto a tabela estiver bloqueada.
Ryaner
2
Também pode ser útil saber que o MyISAM suporta índice espacial, enquanto o InnoDB não. E o MyISAM parece não usar chaves estrangeiras, mesmo que isso não impeça a criação de uma.
kriver
4
@kriver: Você não pode ter chaves estrangeiras nas tabelas MyISAM. Você pode incluir definições de FK nas instruções CREATE TABLE, mas elas (as definições) são simplesmente ignoradas.
usar o seguinte código
191

As pessoas costumam falar sobre desempenho, leituras versus gravações, chaves estrangeiras etc., mas na minha opinião há outro recurso obrigatório para um mecanismo de armazenamento: atualizações atômicas.

Tente o seguinte:

  1. Emita um UPDATE na sua tabela MyISAM que leva 5 segundos.
  2. Enquanto o UPDATE estiver em andamento, digamos 2,5 segundos, pressione Ctrl-C para interrompê-lo.
  3. Observe os efeitos na mesa. Quantas linhas foram atualizadas? Quantos não foram atualizados? A tabela está legível ou foi corrompida quando você pressionou Ctrl-C?
  4. Tente o mesmo experimento com UPDATE em uma tabela do InnoDB, interrompendo a consulta em andamento.
  5. Observe a tabela do InnoDB. Zero linhas foram atualizadas. O InnoDB garantiu que você tenha atualizações atômicas e, se a atualização completa não puder ser confirmada, reverte toda a alteração. Além disso, a tabela não está corrompida. Isso funciona mesmo se você usar killall -9 mysqldpara simular uma falha.

O desempenho é desejável, é claro, mas a perda de dados não deve superar isso.

Bill Karwin
fonte
4
Para o registro, as outras características de um banco de dados ACID - Consistência, Isolamento e Durabilidade - também não são suportadas pelo MyISAM.
precisa
Control-C não deve corromper a tabela - como em CHECK TABLE retornará êxito e todas as consultas continuarão sem erros. O MyISAM abortará a atualização sem atualizar todos os registros, mas a tabela manterá a integridade estrutural interna. Matar o mysqld com o SIGTERM terá o mesmo efeito. No entanto, se você der SIGKILL (kill -9) ou algum sinal de falha (ou ganhar por conta própria ao encontrar um bug), ou se o sistema operacional travar / a energia for perdida, é uma história diferente - você pode ver Corrupção no nível do MyISAM.
Sasha Pachev
1
O InnoDB também pode se corromper na realeza, geralmente mais na realeza que no MyISAM. A ironia do ACID é que temos a noção de tudo ou nada. Portanto, quando o InnoDB não pode fornecer tudo, ele não fornece nada - afirmação interna e se recusa a executar porque um byte em alguma estrutura está errado - 90% do tempo em que poderia ter sido ignorado e afetaria no máximo apenas uma tabela. Servidores Percona recentes têm a opção de lidar com isso - innodb_pass_corrupt_table.
Sasha Pachev
1
Eu estava pesquisando esse tipo de informação nos últimos 3 dias, agora entendi. InnoDB é o melhor. GraçasBill Karwin
user3833682
3
@ flow2k, quase nenhum, atualmente. No meu último trabalho, usamos o MyISAM para uma tabela em um servidor, e o único motivo foi que o MyISAM conseguiu armazenar essa tabela específica em menos espaço do que o InnoDB teria. Como estávamos com pouco espaço em disco, tivemos que usar o MyISAM até podermos mover o banco de dados para outro servidor. No meu novo trabalho, já existe uma política em que todas as tabelas devem ser o InnoDB.
Bill Karwin
138

Eu trabalhei em um sistema de alto volume usando o MySQL e tentei o MyISAM e o InnoDB.

Descobri que o bloqueio no nível da tabela no MyISAM causava sérios problemas de desempenho para nossa carga de trabalho, que se assemelha à sua. Infelizmente, também achei que o desempenho no InnoDB também era pior do que eu esperava.

No final, resolvi o problema de contenção fragmentando os dados para que as inserções entrassem em uma tabela "quente" e selecionassem nunca consultadas a tabela quente.

Isso também permitia que exclusões (os dados eram sensíveis ao tempo e só retinhamos X dias) em tabelas "antigas" que novamente não foram tocadas por consultas selecionadas. O InnoDB parece ter um desempenho ruim nas exclusões em massa; portanto, se você estiver planejando remover os dados, poderá estruturá-los de tal maneira que os dados antigos estejam em uma tabela obsoleta que pode ser simplesmente descartada em vez de executar exclusões.

Claro que não tenho idéia de qual é a sua aplicação, mas espero que isso lhe dê algumas dicas sobre alguns dos problemas do MyISAM e InnoDB.

alanc10n
fonte
3
'No final, resolvi o problema de contenção fragmentando os dados para que as inserções entrassem em uma tabela "quente" e nunca selecionassem a tabela quente. " - não é essencialmente para isso que serve um buffer pool ?
BlueRaja - Danny Pflughoeft
15
Danny - Não, na verdade não. O ajuste das configurações do servidor é importante, mas de forma alguma substitui a estrutura cuidadosa do seu esquema. Se você possui um banco de dados muito, muito maior que a RAM disponível e os padrões de acesso que tocam os dados aleatoriamente em todo o banco de dados, todo o ajuste do buffer pool no mundo não o ajudará. Se você entende os dados e os padrões de acesso, pode mitigar grande parte da dor através de um design cuidadoso.
precisa saber é
66

Um pouco tarde para o jogo ... mas aqui está um post bastante abrangente que escrevi há alguns meses , detalhando as principais diferenças entre o MYISAM e o InnoDB. Pegue uma xícara (e talvez um biscoito) e aproveite.


A principal diferença entre o MyISAM e o InnoDB está na integridade e transações referenciais. Também há outras diferenças, como bloqueios, reversões e pesquisas de texto completo.

Integridade referencial

A integridade referencial garante que os relacionamentos entre as tabelas permaneçam consistentes. Mais especificamente, isso significa que quando uma tabela (por exemplo, Listagens) possui uma chave estrangeira (por exemplo, ID do Produto) apontando para uma tabela diferente (por exemplo, Produtos), quando ocorrem atualizações ou exclusões na tabela apontada, essas alterações são conectadas em cascata ao link mesa. No nosso exemplo, se um produto for renomeado, as chaves estrangeiras da tabela de vinculação também serão atualizadas; se um produto for excluído da tabela 'Produtos', todas as listagens que apontam para a entrada excluída também serão excluídas. Além disso, qualquer nova listagem deve ter essa chave estrangeira apontando para uma entrada válida e existente.

O InnoDB é um DBMS relacional (RDBMS) e, portanto, possui integridade referencial, enquanto o MyISAM não.

Transações e Atomicidade

Os dados em uma tabela são gerenciados usando instruções DML (Data Manipulation Language), como SELECT, INSERT, UPDATE e DELETE. Uma transação agrupa duas ou mais instruções DML juntas em uma única unidade de trabalho, para que a unidade inteira seja aplicada ou nenhuma.

O MyISAM não suporta transações, enquanto o InnoDB suporta.

Se uma operação for interrompida durante o uso de uma tabela MyISAM, a operação será interrompida imediatamente e as linhas (ou mesmo dados em cada linha) afetadas permanecerão afetadas, mesmo que a operação não tenha sido concluída.

Se uma operação for interrompida ao usar uma tabela InnoDB, porque ela usa transações com atomicidade, qualquer transação que não foi concluída não terá efeito, pois nenhuma confirmação é feita.

Bloqueio de tabela vs Bloqueio de linha

Quando uma consulta é executada em uma tabela MyISAM, a tabela inteira na qual está consultando será bloqueada. Isso significa que as consultas subseqüentes serão executadas somente depois que a atual for concluída. Se você estiver lendo uma tabela grande e / ou houver operações frequentes de leitura e gravação, isso pode significar um enorme atraso de consultas.

Quando uma consulta é executada em uma tabela do InnoDB, apenas as linhas envolvidas estão bloqueadas, o restante da tabela permanece disponível para operações CRUD. Isso significa que as consultas podem ser executadas simultaneamente na mesma tabela, desde que não usem a mesma linha.

Esse recurso no InnoDB é conhecido como simultaneidade. Por maior que seja a simultaneidade, existe uma grande desvantagem que se aplica a um intervalo selecionado de tabelas, pois há uma sobrecarga na alternância entre os threads do kernel, e você deve definir um limite nos threads do kernel para impedir que o servidor pare. .

Transações e reversões

Quando você executa uma operação no MyISAM, as alterações são definidas; no InnoDB, essas alterações podem ser revertidas. Os comandos mais comuns usados ​​para controlar transações são COMMIT, ROLLBACK e SAVEPOINT. 1. COMMIT - você pode gravar várias operações DML, mas as alterações serão salvas somente quando um COMMIT for realizado. 2. ROLLBACK - você pode descartar quaisquer operações que ainda não foram confirmadas ainda 3. SAVEPOINT - define um ponto na lista de operações para as quais uma operação ROLLBACK pode reverter para

Confiabilidade

O MyISAM não oferece integridade de dados - falhas de hardware, desligamentos impuros e operações canceladas podem danificar os dados. Isso exigiria reparo ou reconstrução completa dos índices e tabelas.

O InnoDB, por outro lado, usa um log transacional, um buffer de gravação dupla e soma de verificação e validação automáticas para evitar corrupção. Antes de o InnoDB fazer alterações, ele registra os dados antes das transações em um arquivo de espaço de tabela do sistema chamado ibdata1. Se houver uma falha, o InnoDB recuperará automaticamente a reprodução desses logs.

Indexação FULLTEXT

O InnoDB não suporta indexação FULLTEXT até o MySQL versão 5.6.4. No momento da redação deste post, a versão MySQL de muitos provedores de hospedagem compartilhada ainda está abaixo da 5.6.4, o que significa que a indexação FULLTEXT não é suportada pelas tabelas do InnoDB.

No entanto, este não é um motivo válido para usar o MyISAM. É melhor mudar para um provedor de hospedagem que suporte versões atualizadas do MySQL. Não que uma tabela MyISAM que use a indexação FULLTEXT não possa ser convertida em uma tabela InnoDB.

Conclusão

Concluindo, o InnoDB deve ser o seu mecanismo de armazenamento padrão preferido. Escolha MyISAM ou outros tipos de dados quando eles atendem a uma necessidade específica.

d4nyll
fonte
Eu estava fazendo um script de soma de verificação de sessão php e a maioria das minhas chaves são seqüências aleatórias de [az09] ... O Innodb levou mais de 30ms para fazer INSERT ON DUPLICATE KEY UPDATEisso, então tentei o MyISAM e agora é <1ms ... Muitas respostas que vi dizem que O innodb tem dificuldade em lidar com chaves únicas 'não ordenáveis' (sequência aleatória) ... Você tem alguma opinião a nosso respeito? Na verdade, eu estava pensando sobre o impacto que isso teria para usar o MyISAM, mas sua ótima resposta me fez perceber que esse era o caminho a seguir para esse caso específico.
Louis Loudog Trottier
64

Para um carregamento com mais gravações e leituras, você se beneficiará do InnoDB. Como o InnoDB fornece bloqueio de linhas em vez de bloqueio de tabela, seus SELECTs podem ser simultâneos, não apenas entre si, mas também com muitos INSERTs. No entanto, a menos que você pretenda usar transações SQL, defina o InnoDB commit flush como 2 ( innodb_flush_log_at_trx_commit ). Isso oferece muito desempenho bruto que você perderia ao mover tabelas do MyISAM para o InnoDB.

Além disso, considere adicionar replicação. Isso fornece algumas reduções de leitura e, como você declarou que as leituras não precisam estar atualizadas, você pode deixar a replicação para trás um pouco. Apenas certifique-se de que ele pode alcançar qualquer coisa, menos o tráfego mais pesado, ou estará sempre atrasado e nunca alcançará. Se você seguir esse caminho, no entanto, recomendo fortemente que você isole a leitura dos escravos e o gerenciamento de lag de replicação no seu manipulador de banco de dados. É muito mais simples se o código do aplicativo não souber disso.

Por fim, esteja ciente das diferentes cargas de tabela. Você não terá a mesma proporção de leitura / gravação em todas as tabelas. Algumas tabelas menores com quase 100% de leitura podem se dar ao luxo de permanecer no MyISAM. Da mesma forma, se você tiver algumas tabelas com quase 100% de gravação, poderá se beneficiar INSERT DELAYED, mas isso é suportado apenas no MyISAM (a DELAYEDcláusula é ignorada para uma tabela do InnoDB).

Mas referência para ter certeza.

staticsan
fonte
4
O "InnoDB commit flush" você se refere innodb_flush_log_at_trx_commit?
ceejayoz
2
Achei sua postagem muito útil - obrigado. Atualmente, avaliar quando usar o MyISAM / InnoDB para minhas tabelas e sua postagem foi útil. Felicidades.
macacoestrela
2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html estados: Para tabelas MyISAM, se não houver blocos livres no meio do arquivo de dados, as instruções simultâneas SELECT e INSERT serão suportadas. Nessas circunstâncias, você raramente precisa usar INSERIR ATRASO com o MyISAM.
precisa saber é o seguinte
Post muito informativo. Eu tinha a mesma pergunta que as operações e devo dizer que sua postagem me deixou à vontade com a minha decisão sobre o mecanismo de banco de dados. Obrigado! ++
Joe Majewski
Nota rápida: o atraso não é mais suportado no 5.7. Você pode querer testar com LOW_PRIORITY.
Web5 de
59

Para adicionar à ampla seleção de respostas aqui, cobrindo as diferenças mecânicas entre os dois motores, apresento um estudo empírico de comparação de velocidade.

Em termos de velocidade pura, nem sempre o MyISAM é mais rápido que o InnoDB, mas, na minha experiência, ele tende a ser mais rápido nos ambientes de trabalho do PURE READ por um fator de cerca de 2,0-2,5 vezes. Claramente, isso não é apropriado para todos os ambientes - como outros escreveram, o MyISAM carece de coisas como transações e chaves estrangeiras.

Fiz alguns testes comparativos abaixo - usei python para loop e a biblioteca timeit para comparações de tempo. Por interesse, também incluí o mecanismo de memória, que oferece o melhor desempenho geral, embora seja adequado apenas para tabelas menores (você encontra continuamente The table 'tbl' is fullquando excede o limite de memória do MySQL). Os quatro tipos de seleção que eu olho são:

  1. SELECTs de baunilha
  2. conta
  3. SELECTs condicionais
  4. sub-seleciona indexada e não indexada

Primeiramente, criei três tabelas usando o seguinte 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

com 'MyISAM' substituído por 'InnoDB' e 'memory' na segunda e terceira tabelas.

 

1) Baunilha seleciona

Inquerir: SELECT * FROM tbl WHERE index_col = xx

Resultado: empate

Comparação de baunilha selecionada por diferentes mecanismos de banco de dados

A velocidade delas é praticamente a mesma e, como esperado, é linear no número de colunas a serem selecionadas. O InnoDB parece um pouco mais rápido que o MyISAM, mas isso é realmente marginal.

Código:

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) Contagens

Inquerir: SELECT count(*) FROM tbl

Resultado: MyISAM vence

Comparação de contagens por diferentes mecanismos de banco de dados

Este demonstra uma grande diferença entre MyISAM e InnoDB - MyISAM (e memória) controla o número de registros na tabela, portanto, essa transação é rápida e O (1). A quantidade de tempo necessária para a contagem do InnoDB aumenta super linearmente com o tamanho da tabela no intervalo investigado. Suspeito que muitas das acelerações das consultas MyISAM observadas na prática sejam devidas a efeitos semelhantes.

Código:

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) Seleções condicionais

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

Resultado: MyISAM vence

Comparação de seleções condicionais por diferentes mecanismos de banco de dados

Aqui, MyISAM e memória executam aproximadamente o mesmo e superam o InnoDB em cerca de 50% para tabelas maiores. Esse é o tipo de consulta para a qual os benefícios do MyISAM parecem ser maximizados.

Código:

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) Sub-seleciona

Resultado: InnoDB vence

Para esta consulta, criei um conjunto adicional de tabelas para a sub-seleção. Cada uma é simplesmente duas colunas de BIGINTs, uma com um índice de chave primária e outra sem nenhum índice. Devido ao grande tamanho da tabela, não testei o mecanismo de memória. O comando de criação da tabela SQL foi

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

onde mais uma vez, 'MyISAM' é substituído por 'InnoDB' na segunda tabela.

Nesta consulta, deixo o tamanho da tabela de seleção em 1000000 e, em vez disso, vario o tamanho das colunas sub-selecionadas.

Comparação de sub-seleções por diferentes mecanismos de banco de dados

Aqui o InnoDB vence facilmente. Depois de chegarmos a uma tabela de tamanho razoável, os dois mecanismos escalam linearmente com o tamanho do sub-select. O índice acelera o comando MyISAM, mas curiosamente tem pouco efeito na velocidade do InnoDB. subSelect.png

Código:

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) )

Acho que a mensagem de tudo isso é que, se você realmente está preocupado com a velocidade, precisa comparar as consultas que está fazendo, em vez de fazer suposições sobre qual mecanismo será mais adequado.

StackG
fonte
1
o desempenho nem sempre é a única consideração; que tal um gráfico sobre estabilidade? um mecanismo não serve para nada se travar e não suportar recursos básicos do banco de dados.
Pilavdzice
1
O MyISAM provavelmente venceria o InnoDB na maioria das vezes, se o my.cnfarquivo não for otimizado para o InnoDB. Você não mencionou a aparência do seu my.cnfarquivo, que é realmente o fator mais importante para o desempenho do InnoDB.
Itoctopus
Obrigado itoctopus - Gostaria de saber mais sobre as otimizações recomendadas. O código completo usado nesses testes está acima, sinta-se à vontade para repetir os experimentos com várias otimizações e deixe-nos saber se você encontrar alterações significativas nos resultados.
StackG
32

Um pouco fora do tópico, mas para fins de documentação e integridade, gostaria de adicionar o seguinte.

Em geral, o uso do InnoDB resultará em um aplicativo muito menos complexo, provavelmente também mais livre de erros. Como você pode colocar toda a integridade referencial (restrições de chave estrangeira) no modelo de dados, você não precisa nem de perto o código de aplicativo que precisará com o MyISAM.

Toda vez que você inserir, excluir ou substituir um registro, terá que verificar e manter os relacionamentos. Por exemplo, se você excluir um pai, todos os filhos também devem ser excluídos. Por exemplo, mesmo em um sistema de blog simples, se você excluir um registro de publicação de blog, será necessário excluir os registros de comentários, curtidas etc. No InnoDB isso é feito automaticamente pelo mecanismo de banco de dados (se você especificou as restrições no modelo ) e não requer código de aplicativo. No MyISAM, isso terá que ser codificado no aplicativo, o que é muito difícil em servidores da web. Os servidores Web são por natureza muito simultâneos / paralelos e, como essas ações devem ser atômicas e o MyISAM não suporta transações reais, o uso do MyISAM para servidores Web é arriscado / propenso a erros.

Também na maioria dos casos gerais, o InnoDB terá um desempenho muito melhor, por vários motivos, sendo um deles capaz de usar o bloqueio de nível de registro em oposição ao bloqueio no nível de tabela. Não apenas em uma situação em que as gravações são mais frequentes que as leituras, também em situações com junções complexas em grandes conjuntos de dados. Percebemos um aumento de desempenho de três vezes usando as tabelas InnoDB sobre tabelas MyISAM para junções muito grandes (levando alguns minutos).

Eu diria que, em geral, o InnoDB (usando um modelo de dados 3NF completo com integridade referencial) deve ser a opção padrão ao usar o MySQL. O MyISAM deve ser usado apenas em casos muito específicos. Provavelmente terá um desempenho menor, resultando em um aplicativo maior e com mais erros.

Tendo dito isto. Datamodelling é uma arte raramente encontrada entre os webdesigners / programadores. Sem ofensas, mas explica o MyISAM sendo muito usado.

Patrick Savalle
fonte
31

O InnoDB oferece:

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

No InnoDB, todos os dados seguidos, exceto TEXT e BLOB, podem ocupar 8.000 bytes no máximo. Nenhuma indexação de texto completo está disponível para o InnoDB. No InnoDB, o COUNT (*) s (quando WHERE, GROUP BY ou JOIN não é usado) é executado mais lentamente do que no MyISAM porque a contagem de linhas não é armazenada internamente. O InnoDB armazena dados e índices em um arquivo. O InnoDB usa um buffer pool para armazenar em cache dados e índices.

O MyISAM oferece:

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)

O MyISAM possui bloqueio no nível da tabela, mas não no nível de linha. Nenhuma transação. Não há recuperação automática de falhas, mas oferece a funcionalidade da tabela de reparo. Sem restrições de chave estrangeira. As tabelas MyISAM são geralmente de tamanho mais compacto no disco quando comparadas às tabelas do InnoDB. As tabelas MyISAM podem ser ainda mais reduzidas em tamanho compactando com myisampack, se necessário, mas tornam-se somente leitura. O MyISAM armazena índices em um arquivo e dados em outro. O MyISAM usa buffers de chave para armazenar em cache índices e deixa o gerenciamento de armazenamento em cache de dados no sistema operacional.

No geral, eu recomendaria o InnoDB para a maioria dos propósitos e o MyISAM apenas para usos especializados. O InnoDB agora é o mecanismo padrão nas novas versões do MySQL.

Pankaj Khurana
fonte
2
fwiw, VARCHAR no InnoDB também pode ir para páginas excedentes, como BLOB e TEXT. Todos esses tipos de dados são armazenados de forma semelhante internamente.
Bill Karwin
É bom saber, @ BillKarwin! Fazemos uso intenso de VARCHAR em nosso aplicativo e ter VARCHAR contribuindo para esse limite de ~ 8kB foi um pouco preocupante.
Rinogo
Veja mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb para mais detalhes.
Bill Karwin
A resposta ainda não está atualizada, já que o mecanismo innodb no MySQL versão 5.6+ atualmente também suporta indexação de texto completo e o MySQL 5.5 + / 5.7 + suporta tipos de dados espaciais (5.5+) e índices espaciais (r-tee) (5.7+) .. para um melhor suporte você pelo menos precisa ter versão MySQL 5.7+
Raymond Nijland
25

Se você usar MyISAM, você não vai fazer quaisquer transações por hora, a menos que você considere cada instrução DML para ser uma transação (que em qualquer caso, não será durável ou atômica no caso de um acidente).

Portanto, acho que você precisa usar o InnoDB.

300 transações por segundo parecem bastante. Se você absolutamente precisar que essas transações sejam duráveis ​​em caso de falta de energia, verifique se o subsistema de E / S pode lidar com esse número de gravações por segundo facilmente. Você precisará de pelo menos um controlador RAID com cache com bateria.

Se você conseguir um pequeno impacto na durabilidade, poderá usar o InnoDB com innodb_flush_log_at_trx_commit definido como 0 ou 2 (consulte a documentação para obter detalhes), você pode melhorar o desempenho.

Há vários patches que podem aumentar a simultaneidade do Google e de outros - estes podem ser interessantes se você ainda não conseguir desempenho suficiente sem eles.

MarkR
fonte
24

A pergunta e a maioria das respostas estão desatualizadas .

Sim, é um conto de mulheres velhas que o MyISAM é mais rápido que o InnoDB. observe a data da pergunta: 2008; agora é quase uma década depois. O InnoDB fez progressos significativos desde então.

O gráfico dramático foi para o caso em que o MyISAM vence: COUNT(*) sem uma WHEREcláusula. Mas isso é realmente o que você gasta seu tempo fazendo?

Se você executar o teste de simultaneidade , é muito provável que o InnoDB vença, mesmo contraMEMORY .

Se você fizer alguma gravação durante o benchmarking SELECTs, o MyISAM e MEMORYprovavelmente perderá devido ao bloqueio no nível da tabela.

De fato, a Oracle tem tanta certeza de que o InnoDB é melhor que todos removeram o MyISAM da 8.0.

A pergunta foi escrita no início dos dias de 5.1. Desde então, essas versões principais foram marcadas como "Disponibilidade geral":

  • 2010: 5,5 (0,8 em dezembro)
  • 2013: 5.6 (.10 em fevereiro)
  • 2015: 5,7 (0,9 em outubro)
  • 2018: 8.0 (.11 em abr.)

Conclusão: Não use o MyISAM

Rick James
fonte
2
A tecnologia de banco de dados MySQL avança. E as perguntas e respostas do StackOverflow permanecem atoladas no passado. As principais diferenças entre MyISAM e InnoDB são menos sobre a "carga" no servidor, e mais sobre o suporte para a integridade referencial e transações , bem como a simultaneidade e recuperação (+10)
spencer7593
12

Verifique também algumas substituições do MySQL:

MariaDB

http://mariadb.org/

O MariaDB é um servidor de banco de dados que oferece a funcionalidade de substituição do MySQL. O MariaDB foi desenvolvido por alguns dos autores originais do MySQL, com assistência da comunidade mais ampla de desenvolvedores de software livre e de código aberto. Além da funcionalidade principal do MySQL, o MariaDB oferece um rico conjunto de aprimoramentos de recursos, incluindo mecanismos de armazenamento alternativos, otimizações de servidor e patches.

Servidor Percona

https://launchpad.net/percona-server

Um substituto aprimorado para o MySQL, com melhor desempenho, diagnósticos aprimorados e recursos adicionais.

Refinador
fonte
1
Estou usando os dois (Percona em produção, Maria em desenvolvimento de janelas). eles são mais rápidos e funcionam perfeitamente.
Moshe L
4
Isso não responde à pergunta. O MariaDB e o Percona são bifurcações do MySQL e usam os mecanismos InnoDB e MyISAM também.
Dr_
12

Observe que minha educação e experiência formais são com a Oracle, enquanto meu trabalho com o MySQL tem sido totalmente pessoal e no meu tempo, por isso, se eu disser coisas verdadeiras para a Oracle, mas não verdadeiras para o MySQL, peço desculpas. Embora os dois sistemas compartilhem muito, a teoria / álgebra relacional é a mesma e os bancos de dados relacionais ainda são bancos de dados relacionais, ainda existem muitas diferenças!

Gosto particularmente (e também do bloqueio no nível da linha) de que o InnoDB é baseado em transações, o que significa que você pode estar atualizando / inserindo / criando / alterando / descartando / etc várias vezes para uma "operação" do seu aplicativo da web. O problema que surge é que, se apenas algumas dessas alterações / operações forem confirmadas, mas outras não, você na maioria das vezes (dependendo do design específico do banco de dados) acabará com um banco de dados com dados / estrutura conflitantes.

Nota: No Oracle, as instruções create / alter / drop são chamadas "DDL" (Data Definition) e acionam implicitamente uma confirmação. As instruções de inserção / atualização / exclusão, chamadas "DML" (Manipulação de Dados), não são confirmadas automaticamente, mas apenas quando uma DDL, confirmação ou saída / saída é executada (ou se você define sua sessão como "confirmação automática", ou se o seu cliente confirmar automaticamente). É essencial estar ciente disso ao trabalhar com Oracle, mas não tenho certeza de como o MySQL lida com os dois tipos de instruções. Por isso, quero deixar claro que não tenho certeza disso quando se trata do MySQL; somente com Oracle.

Um exemplo de quando os mecanismos baseados em transações são excelentes:

Digamos que eu ou você esteja em uma página da web para se inscrever para participar de um evento gratuito, e um dos principais objetivos do sistema é permitir que apenas 100 pessoas se inscrevam, já que esse é o limite de lugares para o evento. Quando 100 inscrições forem atingidas, o sistema desativará outras inscrições, pelo menos até que outras pessoas sejam canceladas.

Nesse caso, pode haver uma tabela para convidados (nome, telefone, email, etc.) e uma segunda tabela que rastreia o número de convidados que se inscreveram. Portanto, temos duas operações para uma "transação". Agora, suponha que depois que as informações do convidado sejam adicionadas à tabela GUESTS, ocorrerá uma perda de conexão ou um erro com o mesmo impacto. A tabela GUESTS foi atualizada (inserida em), mas a conexão foi perdida antes que os "assentos disponíveis" pudessem ser atualizados.

Agora temos um convidado adicionado à tabela de convidados, mas o número de assentos disponíveis agora está incorreto (por exemplo, o valor é 85 quando na verdade é 84).

É claro que existem muitas maneiras de lidar com isso, como rastrear vagas disponíveis com "número de 100 menos linhas na tabela de convidados" ou algum código que verifica se as informações são consistentes, etc. ... Mas com um banco de dados baseado em transações Em um mecanismo como o InnoDB, TODAS as operações são confirmadas ou NENHUMA delas. Isso pode ser útil em muitos casos, mas, como eu disse, não é a única maneira de estar seguro, não (uma boa maneira, no entanto, é tratada pelo banco de dados, não pelo programador / roteirista).

Isso é tudo "baseado em transações", essencialmente significa, neste contexto, a menos que eu esteja perdendo alguma coisa - que toda a transação seja bem-sucedida como deveria, ou nada seja alterado, pois fazer apenas alterações parciais pode reduzir a bagunça GRAVE da banco de dados, talvez até corrompendo ...

Mas vou dizer mais uma vez, não é a única maneira de evitar fazer uma bagunça. Mas é um dos métodos que o mecanismo manipula, deixando você codificar / script com apenas a necessidade de se preocupar "a transação foi bem-sucedida ou não, e o que eu faço se não (como tentar novamente)" em vez de manualmente escrevendo código para verificá-lo "manualmente" de fora do banco de dados e trabalhando muito mais para esses eventos.

Por fim, uma observação sobre o bloqueio de tabelas e o bloqueio de linhas:

AVISO LEGAL: Eu posso estar errado em tudo o que se segue em relação ao MySQL, e as situações hipotéticas / de exemplo são coisas a serem analisadas, mas eu posso estar errado no que exatamente é possível causar corrupção no MySQL. No entanto, os exemplos são muito reais na programação geral, mesmo que o MySQL tenha mais mecanismos para evitar essas coisas ...

De qualquer forma, estou bastante confiante em concordar com aqueles que argumentam que quantas conexões são permitidas em um momento que não trabalhar em torno de uma tabela bloqueada. De fato, várias conexões são o ponto principal de travar uma mesa !! Para que outros processos / usuários / aplicativos não consigam corromper o banco de dados fazendo alterações ao mesmo tempo.

Como duas ou mais conexões trabalhando na mesma linha tornariam um DIA MUITO MAU para você? Suponha que haja dois processos que ambos desejem / precisem atualizar o mesmo valor na mesma linha, digamos, porque a linha é um registro de um passeio de ônibus, e cada um dos dois processos simultaneamente deseja atualizar os "passageiros" ou "disponíveis_associados" campo como "o valor atual mais 1."

Vamos fazer isso hipoteticamente, passo a passo:

  1. O processo 1 lê o valor atual, digamos que esteja vazio, portanto '0' até agora.
  2. O processo dois também lê o valor atual, que ainda é 0.
  3. Processe uma gravação (atual + 1) que é 1.
  4. O processo dois deve escrever 2, mas, como lê o valor atual antes do processo 1, escreva o novo valor, ele também grava 1 na tabela.

Não tenho certeza de que duas conexões possam se misturar dessa maneira, ambas lendo antes da primeira escrita ... Mas, se não, ainda assim eu veria um problema com:

  1. O processo 1 lê o valor atual, que é 0.
  2. Processe uma gravação (atual + 1), que é 1.
  3. O processo dois lê o valor atual agora. Mas, enquanto o processo de gravação DID de um processo (atualização), ele não confirma os dados, portanto, apenas o mesmo processo pode ler o novo valor atualizado, enquanto todos os outros veem o valor mais antigo, até que haja uma confirmação.

Além disso, pelo menos nos bancos de dados Oracle, existem níveis de isolamento que não vou perder tempo tentando parafrasear. Aqui está um bom artigo sobre esse assunto, e cada nível de isolamento com seus prós e contras, o que acompanha a importância dos mecanismos baseados em transações em um banco de dados ...

Por fim, é provável que existam salvaguardas diferentes no MyISAM, em vez de chaves estrangeiras e interação baseada em transações. Bem, por um lado, há o fato de que uma tabela inteira está bloqueado, o que torna menos provável que as transacções / FKs são necessários .

E, infelizmente, se você estiver ciente desses problemas de simultaneidade, sim, poderá jogá-lo menos seguro e apenas escrever seus aplicativos, configurar seus sistemas para que esses erros não sejam possíveis (seu código é responsável, e não o próprio banco de dados). No entanto, na minha opinião, eu diria que é sempre melhor usar o maior número possível de salvaguardas, programar defensivamente e sempre estar ciente de que é impossível evitar completamente o erro humano. Isso acontece com todos, e quem diz que é imune a isso deve estar mentindo ou não fez mais do que escrever um aplicativo / script "Hello World". ;-)

Espero que ALGUÉM disso seja útil a alguém, e mais ainda, espero que agora não seja apenas o culpado de suposições e ser humano por engano! Peço desculpas se sim, mas é bom pensar nos exemplos, pesquisar o risco e assim por diante, mesmo que não sejam potenciais nesse contexto específico.

Sinta-se à vontade para me corrigir, edite esta "resposta" e até a vote. Apenas tente melhorar, em vez de corrigir uma suposição ruim minha com outra. ;-)

Esta é a minha primeira resposta, então, perdoe o comprimento devido a todas as isenções de responsabilidade, etc ... Só não quero parecer arrogante quando não tenho certeza absoluta!

Arembjorn
fonte
5

Na minha experiência, o MyISAM foi uma escolha melhor, desde que você não faça DELETEs, UPDATEs, muito INSERT, transações e indexação de texto completo. BTW, CHECK TABLE é horrível. À medida que a tabela envelhece em termos de número de linhas, você não sabe quando ela terminará.

yogman
fonte
2
A indexação de texto completo só é possível com o MyISAM, não com o InnoDB.
Pixel Elephant
2
@PixelElephant, isso está começando a mudar no MySQL 5.6. O InnoDB possui um tipo de índice de texto completo, mas até agora não está pronto para o uso em produção IMHO.
Bill Karwin
1
“A indexação de texto completo só é possível com o MyISAM, não com o InnoDB”: não é mais verdade desde o MySQL> = 5.6. Consulte dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57
5

Eu descobri que, embora o Myisam possua contenção de bloqueio, ele ainda é mais rápido que o InnoDb na maioria dos cenários, devido ao esquema de aquisição rápida de bloqueios que ele usa. Eu tentei várias vezes o Innodb e sempre volto ao MyIsam por um motivo ou outro. Além disso, o InnoDB pode consumir muito a CPU em grandes cargas de gravação.

Ricardo
fonte
4

Cada aplicativo tem seu próprio perfil de desempenho para usar um banco de dados, e é provável que ele mude ao longo do tempo.

A melhor coisa que você pode fazer é testar suas opções. Alternar entre o MyISAM e o InnoDB é trivial, então carregue alguns dados de teste e ative o jmeter no seu site e veja o que acontece.

Gary Richardson
fonte
4

Tentei executar a inserção de dados aleatórios nas tabelas MyISAM e InnoDB. O resultado foi bastante chocante. O MyISAM precisou de alguns segundos a menos para inserir 1 milhão de linhas que o InnoDB por apenas 10 mil!

user965748
fonte
2
Você obterá o mesmo desempenho se usar a transação e desativar a confirmação automática para o mecanismo InnoDB.
stanleyxu2005
IDK se o mesmo desempenho, mas é o que eu faço em aplicativos mais complexos e isso acelera.
User965748
1
Você não forneceu os detalhes exatos da sua experiência - quais definições de configuração? O que havia na (s) mesa (s) antes? Que tipo de dados? e talvez o mais importante - houve inserções sequenciais? Paralelo? Qual foi o momento deles? Quantos núcleos de CPU? Tópicos? etc
einpoklum 22/10
3

myisam é um NOGO para esse tipo de carga de trabalho (gravações de alta simultaneidade), não tenho muita experiência com o innodb (testei três vezes e constatei em cada caso que o desempenho foi ruim, mas já faz um tempo desde o último teste) se você não é forçado a executar o mysql, considere experimentar o postgres, pois ele lida com gravações simultâneas MUITO melhor

pfote
fonte
3

Em resumo, o InnoDB é bom se você estiver trabalhando em algo que precisa de um banco de dados confiável que possa lidar com muitas instruções INSERT e UPDATE.

e, MyISAM é bom se você precisar de um banco de dados que, em sua maioria, precisará de muitas instruções de leitura (SELECT), em vez de gravação (INSERT e UPDATES), considerando sua desvantagem no bloqueio de tabela.

você pode querer conferir;
Prós e contras do InnoDB
Prós e contras do MyISAM

Light93
fonte
2

Eu sei que isso não será popular, mas aqui vai:

O myISAM não oferece suporte para itens essenciais do banco de dados, como transações e integridade referencial, que geralmente resultam em aplicativos com falhas / erros. Você não pode aprender os fundamentos adequados do design do banco de dados se eles nem sequer são suportados pelo mecanismo db.

Não usar integridade referencial ou transações no mundo dos bancos de dados é como não usar programação orientada a objetos no mundo do software.

O InnoDB existe agora, use-o! Até os desenvolvedores do MySQL finalmente concordaram em mudar isso para o mecanismo padrão nas versões mais recentes, apesar do myISAM ser o mecanismo original que era o padrão em todos os sistemas legados.

Não, não importa se você está lendo ou escrevendo ou que considerações de desempenho você tem, o uso do myISAM pode resultar em uma variedade de problemas, como o que acabei de encontrar: eu estava executando uma sincronização de banco de dados e ao mesmo tempo outra pessoa acessou um aplicativo que acessou uma tabela configurada para myISAM. Devido à falta de suporte à transação e à confiabilidade geralmente baixa desse mecanismo, houve um travamento no banco de dados inteiro e tive que reiniciar manualmente o mysql!

Nos últimos 15 anos de desenvolvimento, usei muitos bancos de dados e mecanismos. O myISAM bateu em mim cerca de uma dúzia de vezes durante esse período, outros bancos de dados, apenas uma vez! E esse era um banco de dados SQL da Microsoft, onde algum desenvolvedor escreveu código CLR com defeito (Common Language Runtime - basicamente código C # que é executado dentro do banco de dados), a propósito, não foi exatamente a falha do mecanismo de banco de dados.

Eu concordo com as outras respostas aqui que dizem que aplicativos de alta disponibilidade e alto desempenho de qualidade não devem usar o myISAM, pois não funcionará, pois não é robusto ou estável o suficiente para resultar em uma experiência sem frustrações. Veja a resposta de Bill Karwin para mais detalhes.

PS: Adoro quando os fãs do myISAM votam negativamente, mas não consigo dizer qual parte dessa resposta está incorreta.

pilavdzice
fonte
5
Eu não diminuí a votação, mas se o fizesse seria aconselhar nunca usar. a palavra nunca deve ser derrubada no vocabulário de um desenvolvedor ... ressalva sendo 'nunca diga nunca'.
hubson bropa
1

Para essa proporção de leitura / gravação, acho que o InnoDB terá um desempenho melhor. Como você está bem com leituras sujas, você pode (se puder) replicar para um escravo e deixar todas as suas leituras irem para o escravo. Além disso, considere inserir em massa, em vez de um registro por vez.

neal aise
fonte
1

Quase toda vez que inicio um novo projeto, procuro no Google a mesma pergunta para ver se tenho novas respostas.

Eventualmente, tudo se resume a - pego a versão mais recente do MySQL e corro testes.

Eu tenho tabelas onde eu quero fazer pesquisas de chave / valor ... e isso é tudo. Eu preciso obter o valor (0-512 bytes) para uma chave de hash. Não há muitas transações neste banco de dados. A tabela recebe atualizações ocasionalmente (na sua totalidade), mas 0 transações.

Portanto, não estamos falando de um sistema complexo aqui, estamos falando de uma pesquisa simples, e de como (além de tornar a tabela RAM residente) podemos otimizar o desempenho.

Eu também faço testes em outros bancos de dados (ie NoSQL) para ver se há algum lugar em que eu possa obter uma vantagem. A maior vantagem que encontrei está no mapeamento de chaves, mas no que diz respeito à pesquisa, o MyISAM está no topo de todas.

Embora eu não realizasse transações financeiras com tabelas MyISAM, mas para pesquisas simples, você deve testá-lo. Normalmente 2x a 5x as consultas / s.

Teste, congratulo-me com o debate.

Cyberwip
fonte
1

Se houver 70% de inserções e 30% de leitura, é mais parecido com o lado do InnoDB.

kta
fonte
0

Conclusão: se você estiver trabalhando offline com seleções em grandes quantidades de dados, o MyISAM provavelmente fornecerá velocidades melhores (muito melhores).

existem algumas situações em que o MyISAM é infinitamente mais eficiente que o InnoDB: ao manipular grandes despejos de dados offline (devido ao bloqueio da tabela).

exemplo: eu estava convertendo um arquivo csv (15 milhões de registros) do NOAA, que usa campos VARCHAR como chaves. O InnoDB estava demorando uma eternidade, mesmo com grandes pedaços de memória disponíveis.

este é um exemplo do csv (o primeiro e o terceiro campos são chaves).

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,

Como o que eu preciso fazer é executar uma atualização offline em lote dos fenômenos climáticos observados, uso a tabela MyISAM para receber dados e executo JOINS nas chaves para poder limpar o arquivo recebido e substituir os campos VARCHAR por chaves INT (que estão relacionadas a tabelas externas em que os valores originais do VARCHAR estão armazenados).

Tony Gil
fonte