Acelerando a conversão do MyISAM para InnoDB

15

Eu tenho um servidor mysql 5.1 com um banco de dados de aproximadamente 450 tabelas, ocupando 4 GB. A grande maioria dessas tabelas (com exceção de 2) é MyIsam. Isso tem sido bom na maioria das vezes (não precisa de transações), mas o aplicativo está obtendo tráfego e determinadas tabelas foram impactadas devido ao bloqueio de tabelas nas atualizações. Essa é a razão pela qual 2 das tabelas são do InnoDB agora.

A conversão nas tabelas menores (100 mil linhas) não leva muito tempo, causando um tempo de inatividade mínimo. No entanto, algumas das minhas tabelas de rastreamento estão se aproximando de 50 milhões de linhas. Existe uma maneira de acelerar um jogo ALTER TABLE...ENGINE InnoDBem grandes mesas? E, se não, existem outros métodos para converter minimizar o tempo de inatividade nessas tabelas com muita gravação?

Derek Downey
fonte
11
Algo a ter em mente: várias perguntas em uma única postagem tendem a desencorajar as pessoas que podem responder uma delas a postar uma resposta.
BenV
Eu VtC, pois isso é bastante complicado de responder. Você deve abrir várias perguntas individualmente.
jcolebrand
terei prazer em seguir o conselho para transformá-lo em uma única pergunta, mas é recomendável excluir essa pergunta e abrir uma nova? a reescrita iria ser maioritariamente removendo o segundo 2 balas e alterando o primeiro (que eu atualizei o título, assim como para refletir quais mecanismos de armazenamento)
Derek Downey
Qualquer um estaria bem. Geralmente, é mais fácil escrever duas outras perguntas e excluir uma. No entanto, você pode facilmente deixar este como "referência" e fazer com que os outros dois se refiram a ele, como uma pergunta "este é meu objetivo geral".
jcolebrand
edite este em um marcador e poste as perguntas a seguir.
Brian Ballsun-Stanton

Respostas:

10

Deixe-me começar dizendo: eu odeio o ALTER. É mau, IMHO.

Digamos, este é seu esquema de tabela atual -

CREATE TABLE my_table_of_love (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=MyISAM CHARSET=utf8;

Aqui está o caminho que eu recomendo -

Crie um novo objeto de tabela que substitua o antigo:

CREATE TABLE my_table_of_love_NEW (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
my_value VARCHAR(40),
date_created DATE,
PRIMARY KEY(id)
) ENGINE=InnoDB CHARSET=utf8

Insira todas as linhas da tabela antiga por nome na nova tabela:

INSERT INTO my_table_of_love_NEW (id,my_value,date_created)
SELECT id,my_value,date_created FROM my_table_of_love;

Fumo teste sua migração:

SELECT COUNT(*) FROM my_table_of_love_NEW;
SELECT COUNT(*) FROM my_table_of_love;
SELECT a.id,a.my_value,a.date_created FROM my_table_of_love_NEW a
LEFT JOIN my_table_of_love b ON (b.id = a.id)
WHERE a.my_value != b.my_value;

Troque os nomes das tabelas para que você possa manter um backup caso precise reverter.

RENAME TABLE my_table_of_love TO my_table_of_love_OLD;
RENAME TABLE my_table_of_love_NEW TO my_table_of_love;

Prossiga para o teste de regressão.

Essa abordagem se torna cada vez mais preferível com tabelas com vários índices e milhões de linhas.

Pensamentos?

randomx
fonte
11
Concordo ... embora, se for muito transacional, você pode precisar reduzir o banco de dados enquanto faz isso. (mas uma tabela alter vai dar-lhe um longo período de inatividade, o mais provável)
Joe
Sim, achei que seria necessário tempo de inatividade para as tabelas mais ativas. Vou ter que executar alguns testes, mas por que ALTER TABLEdemoraria mais do que INSERT INTO...SELECT50 milhões de linhas?
Derek Downey
Não vai. Basicamente, o MySQL faz internamente exatamente como este pôster sugeriu. Ele cria uma cópia da definição e carrega rapidamente a cópia.
Morgan Tocker 22/03
Eu gosto desse método porque ignora a parte "copy to tmp", que pode levar algum tempo para tabelas grandes.
quer
Deixe-me acrescentar agora que, no MySQL 5.7, os ALTERs são muito mais rápidos e fáceis de lidar.
randomx 28/03
7

1) A proteção contra perdas é uma função da paranóia. Sempre faça um backup. Se você é realmente paranóico, faça um backup e restaure-o.

2) Esta página do manual do MySQL possui instruções para converter tipos de tabelas.

A maneira mais rápida de alterar uma tabela para o InnoDB é fazer as inserções diretamente em uma tabela do InnoDB. Ou seja, use ALTER TABLE ... ENGINE = INNODB ou crie uma tabela InnoDB vazia com definições idênticas e insira as linhas com INSERT INTO ... SELECT * FROM ....

3) O PostgreSQL faz pesquisa de texto completo , o Sphinx Engine parece fazer isso no MySQL

Brian Ballsun-Stanton
fonte
Definitivamente vou investigar a esfinge, como só ouvi falar recentemente.
Derek Downey
3

É X vezes mais fácil otimizar o servidor inteiro (configuração de memória, caches, índices) quando você possui apenas um mecanismo. Misturar o myisam com o innodb em bancos de dados grandes sempre fica preso em algum momento forçado por alguns a fazer com que o mecanismo funcione bem (mas não é excelente :)

Eu recomendo que você se interesse por alguns mecanismos de pesquisa de texto completo, como sphinx , lucene ( solr ) e se livre da camada do banco de dados.

sbczk
fonte