Fiz muita pesquisa sobre como manter índices no MySQL para impedir a fragmentação e otimizar de alguma forma a execução de algumas consultas.
Eu estou familiarizado com essa fórmula que calcula a proporção entre o espaço máximo disponível para uma tabela e o espaço usado por dados e índices.
No entanto, minhas principais perguntas ainda não foram respondidas. Talvez isso se deva ao fato de eu estar familiarizado com a manutenção de índices no SQL Server e ter a tendência de pensar que no MySQL deve ser algo semelhante.
No SQL Server, você pode ter vários índices e cada um deles pode ter diferentes níveis de fragmentação. Em seguida, você pode escolher um e executar uma operação 'REORGANIZE' ou 'REBUILD' nesse índice específico, sem afetar o restante.
Que eu saiba, não existe uma 'fragmentação de tabela' e o SQL Server não fornece nenhuma ferramenta para corrigir a 'fragmentação de tabela'. O que ele fornece são ferramentas para verificar a fragmentação do índice (entendida como a proporção entre o número de páginas usadas por um índice e a plenitude dessa página e contiguidade), bem como a fragmentação interna e externa.
Tudo isso é bastante simples de entender, pelo menos para mim.
Agora, quando chega a hora de manter índices no MySQL, existe apenas o conceito de 'fragmentação de tabela', como mencionado acima.
Uma tabela no MySQL pode ter vários índices, mas quando eu checo a 'taxa de fragmentação' com essa famosa fórmula, não vejo a fragmentação de cada índice, mas a tabela como um todo.
Quando quero otimizar os índices no MySQL, não escolho um índice específico para operar (como no SQL Server). Em vez disso, eu faço uma operação 'OPTIMIZE' em toda a tabela, o que presumivelmente afeta todos os índices.
Quando a tabela é otimizada no MySQL, a proporção entre o espaço usado pelos dados + índices e o espaço geral é reduzida, o que sugere algum tipo de reorganização física no disco rígido, o que se traduz em uma redução do espaço físico. No entanto, a fragmentação do índice não se refere apenas ao espaço físico, mas à estrutura da árvore que foi alterada ao longo do tempo devido a inserções e atualizações.
Finalmente, consegui uma tabela no InnoDB / MySQL. Essa tabela possui 3 milhões de registros, 105 colunas e 55 índices. São 1,5 GB, excluindo índices, que são 2,1 GB.
Essa tabela está sendo atingida milhares de vezes por dia para atualização e inserção (na verdade, não excluímos registros).
Essa tabela foi criada há anos e eu tenho certeza de que ninguém mantém nenhum índice.
Eu esperava encontrar uma enorme fragmentação lá, mas quando eu executo o cálculo de fragmentação conforme prescrito
free_space / (data_length + index_length)
Acontece que eu tenho apenas uma fragmentação de 0,2%. IMHO que é bastante irreal.
Portanto, as grandes questões são:
- Como verifico a fragmentação de um índice específico no MySQL, não a tabela como um todo
- O OPTIMIZE TABLE realmente corrige a fragmentação interna / externa de um índice como no SQL Server?
- Quando otimizo uma tabela no MySQL, ele realmente recria todos os índices da tabela?
- É realista pensar que reduzir o espaço físico de um índice (sem reconstruir a própria árvore) realmente se traduz em um melhor desempenho?
fonte
Respostas:
A fragmentação do índice é muito superestimada. Não se preocupe com isso.
Dois blocos adjacentes, um tanto vazios, são mesclados pelo InnoDB como o processamento natural.
Ações aleatórias em um BTree fazem com que ele gravite naturalmente em direção a uma média de 69% da capacidade total. Claro, isso não é 100%, mas a sobrecarga de "consertar" não vale a pena.
SHOW TABLE STATUS
fornece algumas métricas, mas são falhas - "Data_free" inclui certo espaço "livre", mas não outro espaço "livre".Há espaço não utilizado em cada bloco; blocos gratuitos de 16 KB; "extensões" livres (pedaços de nMB); Linhas MVCC aguardando para serem colhidas; nós não-folha têm sua própria fragmentação; etc.
A Percona e a Oracle têm maneiras diferentes de ver o tamanho (número de blocos) de um índice. Acho que nenhum deles é útil por causa da definição limitada de "livre". Parece que os blocos (16 KB cada) são alocados em blocos (vários MB), levando-os a acreditar que há todo tipo de fragmentação. Na realidade, geralmente é apenas a maioria de um desses blocos com vários MB. E
OPTIMIZE TABLE
não recupera necessariamente nada do espaço.Se o SQL Server estiver usando o BTrees, é mentira dizer que "não há fragmentação". Pense no que acontece em uma "divisão de bloco". Ou pense na sobrecarga de desfragmentar continuamente. De qualquer maneira você perde.
Observe também que uma tabela e um índice são estruturas essencialmente idênticas:
Se você tiver
innodb_file_per_table = ON
, poderá ver claramente o encolhimento (se houver) após OPTIMIZE TABLE observando o.ibd
tamanho do arquivo. PoisOFF
, as informações estão ocultasibdata1
, masSHOW TABLE STATUS
podem ser razoavelmente precisas, pois todo o espaço "livre" pertence a todas as tabelas. Bem, exceto pelos pedaços pré-alocados.Você pode perceber que uma tabela de arquivo por tabela recém-otimizada possui exatamente 4M, 5M, 6M ou 7M de Data_free. Novamente, essa é a pré-alocação e a falha em fornecer os detalhes minuciosos.
Eu trabalho com o InnoDB há mais de uma década; Eu trabalhei com milhares de tabelas diferentes, grandes e pequenas. Eu digo que apenas uma mesa em cada mil precisa realmente
OPTIMIZE TABLE
. Usá-lo em outras mesas é um desperdício.105 colunas é muito, mas talvez não muitas.
Você tem 55 índices em uma tabela? Isso é mau. São 55 atualizações por
INSERT
. Vamos discutir isso mais. Tenha em mente queINDEX(a)
é inútil se você também tiverINDEX(a,b)
. EINDEX(flag)
é inútil por causa da baixa cardinalidade. (MasINDEX(flag, foo)
pode ser útil.)T1: Não há uma boa maneira de verificar todas as formas de fragmentação nos dados ou nos índices secundários.
Q2, Q3:
OPTIMIZE TABLE
reconstrói a tabela porCREATEing
uma nova tabela eINSERTing
todas as linhas, depoisRENAMEing
eDROPping
. A reinserção dos dados na ordem PK garante que os dados sejam bem desfragmentados. Os índices são outra questão.Q4: você pode
DROP
ereCREATE
cada índice para limpá-lo. Mas este é um processo extremamente lento. A versão 5.6 tem algumas melhorias, mas não sei se elas ajudam na desfragmentação.Também é possível
ALTER TABLE ... DISABLE KEYS
, entãoENABLE
eles. Isso pode resultar em uma reconstrução mais eficiente de todos os índices secundários de uma só vez.fonte
Passar.
Ele reconstrói completamente a tabela e seus índices.
Essa é a mesma pergunta com a mesma resposta.
Não é realista pensar que você poderia reduzir o espaço sem reconstruir a árvore. Eles vão juntos.
fonte
SHOW TABLE STATUS LIKE 'mytable'
daria uma dica nadata free
coluna. dev.mysql.com/doc/refman/5.6/en/show-table-status.html