Por que usar innodb_file_per_table?

27

Existem muitos artigos exagerando (IMHO, é claro) a necessidade innodb_file_per_table. Eu entendo que com innodb_file_per_table, deve haver um melhor controle sobre as tabelas individuais; como fazer backup de cada tabela separadamente. No entanto, a reivindicação de melhor desempenho é questionável.

No meu teste, não há diferença no desempenho de innodb_file_per_tablee ibdata1para um banco de dados de 60 GB. Obviamente, foi um teste simples com consultas normais e a situação pode ser diferente para consultas complicadas na vida real (esse é o motivo pelo qual eu fiz essa pergunta). O Linux de 64 bits ext4pode lidar efetivamente com arquivos grandes.

Com innodb_file_per_table, são necessárias mais operações de E / S de disco; e isso é significativo em se complicado JOINe FOREIGN KEYrestrições.

O espaço de tabela é compartilhado em um único ibdata; como os espaços de tabela dedicados para tabelas separadas podem economizar espaço em disco? Obviamente, é mais fácil liberar espaço para cada tabela ALTER, mas ainda é um processo caro (com bloqueio de tabela).

PERGUNTA: Isso innodb_file_per_tableafeta um melhor desempenho do mysql? Se sim, por que?

Googlebot
fonte
Veja esta resposta à minha pergunta: dba.stackexchange.com/questions/7924/… também pode ajudar.
KM.

Respostas:

19

Não acho que seja uma questão de desempenho, mas de gerenciamento.

Com um arquivo separado por tabela, você pode armazenar diferentes bancos de dados em diferentes dispositivos de armazenamento, por exemplo.

Você pode lidar com o caso de bancos de dados muito grandes em sistemas de arquivos que não podem manipular arquivos grandes (pelo menos adie o problema até que uma tabela atinja o limite de tamanho do arquivo).

Você não tem crescimento descontrolado de espaço de tabela. Se você tiver algumas tabelas grandes descartadas, o ibdataarquivo permanecerá pequeno.

Um aspecto que pode ter algum efeito no desempenho é a fragmentação dos dados e índices da tabela, que serão limitados por tabela. Mas isso precisa ser testado para ser confirmado.

ypercubeᵀᴹ
fonte
O crescimento do espaço de tabela é exatamente o que você deseja innodb_file_per_table.
Sj #
13

Por que usar innodb_file_per_table?

Porque é mais fácil gerenciar indivíduos, pois isso pode ser feito no nível do arquivo. Isso significa que, mesmo que o servidor esteja inoperante, você ainda pode copiar os dados copiando os arquivos da tabela, enquanto usar um espaço de tabela compartilhado significa copiar tudo o que pode ser desnecessariamente grande ou encontrar uma maneira de fazer o servidor executar a extração de dados ( você realmente não deseja extrair manualmente os dados com um editor hexadecimal).

Alguém avisou que você não pode simplesmente copiar e colar .ibdarquivos de um servidor para outro. Isso pode ser verdade, mas não deve se aplicar a backups no mesmo servidor (estou usando o termo backup aqui no sentido tradicional de fazer uma cópia; ou seja, não alterando drasticamente a coisa toda). Além disso, ibdata1é recriado automaticamente na inicialização (como visto na etapa de exclusãoibdata1 da maioria dos guias de “conversão em arquivo por tabela”). Como tal, você não precisa copiar ibdata1além dos seus .ibdarquivos (e seus .frmarquivos correspondentes etc.).

Se estiver tentando recuperar uma tabela perdida, deve ser suficiente copiar o arquivo .ibde .frm, além de information_schema(que é muito menor que ibdata1). Dessa forma, você pode colocá-los em um servidor fictício e extrair sua tabela sem ter que copiar toda a coisa enorme.

No entanto, a reivindicação de melhor desempenho é questionável. … Com innodb_file_per_table, são necessárias mais operações de E / S de disco; e isso é significativo em restrições JOINs e FOREIGN KEY complicadas.

Não é de surpreender que o desempenho dependa inteiramente dos bancos de dados específicos em uso. Uma pessoa terá (até muito) resultados diferentes de outra.

É verdade que haverá mais operações de E / S de disco com arquivo por tabela, mas apenas um pouco mais. Pense em como o sistema funciona.

  • Para um banco de dados monolítico:

    1. Servidor iniciado
    2. ibdata1 está aberto
    3. Cabeçalho e metadados são lidos
    4. Estruturas e metadados são armazenados em cache na memória
    5. As consultas acontecem
      1. O servidor acessa o disco e lê os dados do já aberto ibdata1
      2. O servidor pode armazenar em cache os dados na memória
  • Para um banco de dados por tabela:

    1. Servidor iniciado
    2. ibdata1 está aberto
    3. Cabeçalho e metadados são lidos
    4. Cada .ibdarquivo individual é aberto
    5. Cabeçalho e metadados são lidos em cada .ibdarquivo
    6. Estruturas e metadados são armazenados em cache na memória
    7. As consultas acontecem
      1. O servidor acessa o disco e lê os dados do .ibdarquivo já aberto
      2. O servidor pode armazenar em cache os dados na memória

Você notará que, quando o servidor está em execução, não é possível mover os arquivos de dados porque o servidor possui identificadores abertos. Isso ocorre porque, ao iniciar, ele os abre e os deixa abertos. Não os abre e fecha para cada consulta individual.

Como tal, há apenas mais algumas operações de E / S no início, quando o servidor é inicializado; não enquanto estiver em execução. Além disso, embora cada .ibdarquivo individual tenha sua própria sobrecarga separada (assinaturas, estruturas etc.), eles são armazenados em cache na memória e não são lidos novamente para cada consulta. Além disso, as mesmas estruturas são lidas mesmo com um espaço de tabela compartilhado, portanto, quase não há (se é que existe) mais memória necessária.

O innodb_file_per_table afeta o desempenho do mysql?

Na verdade, se houver, o desempenho pode ser de fato pior .

Ao usar um espaço de tabela compartilhado, as operações de leitura e gravação podem às vezes / frequentemente ser combinadas para que o servidor leia uma amostra de dados de várias tabelas de uma só vez ibdata.

No entanto, se os dados estiverem espalhados entre vários arquivos, ele deverá executar uma operação de E / S separada para cada um individualmente.

É claro que isso novamente depende inteiramente do banco de dados em questão; o impacto no desempenho do mundo real dependeria do tamanho, da frequência da consulta e da fragmentação interna do espaço de tabela compartilhado. Algumas pessoas podem notar uma grande diferença, enquanto outras podem não ter nenhum impacto.

O espaço de tabela é compartilhado em um único ibdata; como os espaços de tabela dedicados para tabelas separadas podem economizar espaço em disco?

Isso não. Se alguma coisa, aumenta o uso do disco.

Não tenho um banco de dados de 60 GB para testar, mas meu "insignificante" banco de dados pessoal, que contém minha instalação do WordPress e algumas tabelas pequenas para uso pessoal e testes de desenvolvimento, pesavam ~ 30 MB ao usar um espaço de tabela compartilhado. Depois de convertê-lo em arquivo por tabela, ele aumentou para ~ 85 MB. Mesmo eliminando tudo e reimportando, ele ainda tinha mais de 60 MB.

Esse aumento é devido a dois fatores:

  • O tamanho mínimo absoluto para ibdata1é - por algum motivo - 10 MB, mesmo que você não tenha nada além de information_schemaarmazenado.

  • Com um espaço de tabela compartilhado, só ibdata1há sobrecarga, como assinaturas de arquivos, metadados, etc., mas com cada tabela, cada .ibdarquivo individual tem tudo isso. Isso significa que o total (mesmo com um hipotético <10MB ibdata1) seria um pouco maior em pelo menos:

    GetTotalSizeofOverhead() * GetNumTables()

Obviamente, esses não serão grandes aumentos (a menos que você esteja usando um host que limite o tamanho do banco de dados ou os armazene em uma unidade flash etc.), mas eles aumentam mesmo assim e ao alternar ( todas ) as tabelas para arquivos Por tabela, você pode reduzir ibdata1para 10 MB, o total geral será invariavelmente mais do que era.

Synetech
fonte
11

Esta é a minha razão para SEMPRE usar innodb_file_per_table:

Sem arquivo por tabela, o arquivo ibdata nunca comprime, encolhe ou diminui o espaço. Não quando você exclui uma linha, descarta uma tabela ou um banco de dados. 2 GB de dados podem se tornar um arquivo de 20 GB rapidamente, se você tiver um sistema de filas ativo.

Digamos que você queira fazer um backup da sua tabela atual de 1 GB antes de uma alteração e soltá-la depois. Você está preso com um GB de espaço agora não utilizado no seu ibdata. Vadio.

Provavelmente existem infinitos exemplos de casos em que medidas temporárias aumentam o arquivo de dados único, mas basta dizer que, na minha opinião, nunca há uma razão para NÃO usar innodb_file_per_table

Além disso, aqui está um bom post para ler: http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table

randomx
fonte
11
Percebi que é bom SEMPRE fazê-lo também. Matrizes de armazenamento magnético suportadas por SSDs podem lidar com caches de leitura / gravação de forma mais eficaz em arquivos menores para tabelas. Para várias tabelas que% 99,99 das vezes são 'lidas', mas não gravadas, elas sempre estão no cache do controlador de armazenamento, o que representa uma grande redução no tempo de resposta.
Sdkks
5

Minha razão pela qual não usar innodb_file_per_table é desempenho.

Fiz alguns testes para nosso banco de dados com 450 tabelas no mysql 5.5.45 Linux CentOS versão 6.7

Para testes de unidade que inserem dispositivos elétricos no banco de dados antes de cada teste (não usando todas as tabelas todas as vezes) e também os testes em si funcionam muito com o banco de dados (inserções, atualizações, exclusões, seleções ), o desempenho era 3-5 vezes melhor quando as tabelas de banco de dados não eram separados em mais arquivos.

Eu recomendo testar seu banco de dados com as consultas que você deseja usar e compará-lo antes de decidir usar innodb_file_per_table

Talvez você descubra que, para o servidor de produção, você pode usar innodb_file_per_table, mas para o ambiente de IC (continua a integração) que inicia testes de unidade (usa muito o banco de dados) e também é melhor desenvolvedores que iniciam muito os testes de unidade por causa do desempenho.

Tomor
fonte
2
Acho que isso se deve ao tempo necessário para alocar os arquivos iniciais para todas as 450 tabelas vs alocar um único arquivo. Na produção, isso acontecerá apenas uma vez; portanto, não deve ser um problema, mas você deve enfatizar que, para criar rapidamente um banco de dados e depois destruí-lo completamente e repetir várias vezes um único arquivo ibdata, é melhor.
ColinM 01/04
2

Isso torna os dados mais gerenciáveis, porque você pode recuperar o espaço não utilizado, o que é bom.

Acho que se seu banco de dados for usado principalmente para consultas selecionadas, isso não afetará muito o desempenho. Ele ainda precisa ler sobre a mesma quantidade de dados. Acho que não importa muito de quais arquivos está lendo os dados.

No entanto, isso pode piorar o desempenho em um banco de dados que faz muitas inserções e atualizações. Isso ocorre porque o mysql chama fsync () no arquivo de armazenamento após você confirmar uma transação. Se houver um único arquivo, ele faz uma chamada e aguarda a conclusão da chamada. Se houver muitos arquivos, ele precisará fazer a chamada várias vezes e aguardar o retorno de todas essas chamadas antes que o comando commit possa retornar.

Aqui está uma postagem de alguém que teve esse problema: http://umangg.blogspot.com/2010/02/innodbfilepertable.html

Sarel Botha
fonte
2

Conforme o artigo abaixo, o desempenho não é sobre gerenciamento de dados (operações brutas), mas sobre criação e descarte de objetos.

innodb_file_per_table torna a criação massiva e a eliminação de objetos mais lentas que o armazenamento ibdata e a produção não é aplicável, mas o teste contínuo deve ser relevante.

https://www.percona.com/blog/2015/02/24/mysqls-innodb_file_per_table-slowing/

Flavio Peinado
fonte