Adicionando índice a grandes tabelas mysql

13

Eu tenho uma mesa

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) não assinado NOT NULL AUTO_INCREMENT,
installmentint (10) não assinado NOT NULL,
on_datedata NOT NULL,
actual_datedata DEFAULT NULL,
payment_typeint (11) NOT NULL,
scheduled_principal_outstandingdecimal (65,0) NOT NULL,
scheduled_principal_duedecimal (65,0) NOT NULL,
scheduled_interest_outstandingdecimal (65,0) NOT NULL,
scheduled_interest_duedecimal (65,0) NOT NULL,
currencyint (11) NOT NULL,
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime NOT NULL DEFAULT ' 2013-01-06 14:29:16 ',
loan_base_schedule_idint (10) unsigned NOT NULL,
lending_idint (10) unsigned NOT NULL,
rescheduletinyint (1) PADRÃO' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
KEY index_bslt_lending(lending_id),
KEY index_bslt_actualdate( actual_date),
KEY index_bslt_spsila ( loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
KEY index_bslt_ondate( on_date),
KEY index_bslt_oa( on_date, actual_date),
KEY index_bslt_ol( on_date, loan_base_schedule_id),
KEY index_bslt_oli( on_date, lending_id)
) ENGINE = InnoDB AUTO_INCREMENT = 30410126 PADRÃO charset = UTF-8 |

Agora, esta tabela possui 30 milhões de registros, preciso adicionar mais dois índices a isso e é como se demorasse anos para adicioná-lo.

alter table base_schedule_line_items adiciona índice index_bslt_sla (data_principal_programada, data_atual, id_de_prestação);
alterar tabela base_schedule_line_items adicionar índice index_bslt_ssla (data_principal_programada, data_processo_interessante, data_de_prestação, data_idual);

Eu usei a consulta abaixo mencionada para descobrir o tamanho da tabela

SELECT table_name AS "Tables", round (((data_length + index_length) / 1024/1024), 2) "Tamanho em MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

O resultado saiu como

base_schedule_line_items | 20111.00

Eu usei isso apenas para calcular o comprimento dos dados e deixei de fora o comprimento do índice

SELECT table_name AS "Tables", round (((data_length) / 1024/1024), 2) "Tamanho em MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

e o resultado foi

base_schedule_line_items | 9497,00

Os índices

Index_bslt_actualdate CHAVE (actual_date),
index_bslt_spsila CHAVE (loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
CHAVE index_bslt_ondate (on_date),
CHAVE index_bslt_oa (on_date, actual_date),
CHAVE index_bslt_ol (on_date, loan_base_schedule_id),
index_bslt_oli CHAVE (on_date, lending_id)

foram adicionados por mim, mas não tenho certeza ou para qual finalidade outros índices foram adicionados. Esta é uma aplicação bastante grande. Agora, preciso adicionar esses dois índices mencionados acima, pois eles me ajudam a extrair um relatório usando uma instrução select e acho muito difícil adicioná-los. Qualquer ajuda seria muito apreciada

user2294477
fonte

Respostas:

16

A atividade de alterar tabelas grandes é feita em fases:

  1. Crie uma nova tabela com campos e índices obrigatórios, digamos no banco de dados de teste (apenas estrutura)
  2. Despejar os dados da tabela existente e carregar o mesmo na tabela recém-criada no banco de dados de teste
  3. Agora anuncie seu tempo de inatividade :)
  4. Troque as tabelas renomeando - RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;Esta é uma operação atômica que leva uma fração de segundo.
  5. Carregue os registros extras na tabela recém-criada (os registros que vieram após o dumping e o carregamento). Esta etapa pode ser realizada antes da Etapa 3, também uma vez para reduzir o tempo de inatividade.
  6. E seu sistema está de volta

Algumas notas:

  1. Você não precisa acessar o esquema de informações diretamente assim, tente usar SHOW TABLE STATUS from db like 'table_name'
  2. A velocidade da tabela de alteração está mais ou menos vinculada à velocidade de E / S. Na última vez em que executamos uma tabela de alteração direta (sem as etapas acima), tínhamos um tamanho de tabela de 40 GB +, que demorava cerca de 4 horas. Se seus dados de 20 GB estão demorando anos, você está trabalhando em alguma máquina desatualizada.
  3. Também a queda dos índices indesejados, index_bslt_ondate, index_base_schedule_line_items_loan_base_schedulecomo alguns outros índices, tem a coluna mais à esquerda como a coluna indexada

Entre em contato se precisar de esclarecimentos sobre qualquer uma dessas etapas.

Edit: Um script python simples para automatizar o processo https://github.com/georgecj11/hotswap_mysql_table.git

georgecj11
fonte
10

Você pode usar uma ferramenta como pt-online-schema-change para adicionar o índice sem bloquear seu aplicativo. A lógica básica é a seguinte:

  • crie uma cópia vazia da tabela com o novo índice
  • adicione gatilhos à tabela existente para que quaisquer alterações que atinjam a tabela sejam aplicadas à cópia da tabela *
  • comece a copiar as linhas da tabela antiga para a nova
  • Quando a cópia estiver concluída, troque as tabelas
  • largar a mesa velha

* A ferramenta não funciona se houver gatilhos existentes na mesa

O comportamento de troca e descarte pode ser ajustado com base nas opções passadas para a ferramenta.

Além disso, há problemas com chaves estrangeiras, portanto, leia a documentação da ferramenta para entender completamente o que está fazendo.

E, claro, é aconselhável garantir que você tenha um backup da tabela para poder restaurar, se necessário.

Derek Downey
fonte