Pergunta

Eu tenho um banco de dados enorme MySQL (InnoDB), com milhões de linhas na tabela de sessões que foram criados por um rastreador não relacionado, o mau funcionamento em execução no mesmo servidor como o nosso. Infelizmente, eu tenho que corrigir a bagunça agora.

Se eu tentar truncate table sessions; parece tomar um tempo demasiado longo (mais de 30 minutos). Eu não me importo sobre os dados; Eu só quero ter a tabela eliminada tão rapidamente quanto possível. Existe uma maneira mais rápida, ou vou ter que ficar para fora durante a noite?

Foi útil?

Solução

A maneira mais rápida é usar DROP TABLE para remover a tabela completa e recriá-lo usando a mesma definição. Se você não tem restrições de chave estrangeira sobre a mesa, então você deve fazer isso.

Se você estiver usando o MySQL versão maior do que 5.0.3, isto acontece automaticamente com um TRUNCATE. Você pode obter algumas informações úteis para fora do manual, bem como, que descreve como um TRUNCATE trabalha com restrições FK. http://dev.mysql.com/doc/refman/5.0 /en/truncate-table.html

EDIT: TRUNCATE não é o mesmo que uma gota ou um DELETE FROM. Para aqueles que estão confusos sobre as diferenças, consulte o link manual acima. TRUNCATE vai agir o mesmo que uma gota se ele pode (se não houver do FK), caso contrário, ele age como um DELETE FROM com nenhum onde cláusula.

Outras dicas

(Como este apareceu no alto de resultados do Google, pensei um pouco mais de instrução pode ser útil.)

MySQL tem uma maneira conveniente de criar mesas vazias como tabelas existentes, e um comando atômica tabela de renomeação. Juntos, esta é uma maneira rápida para limpar dados:

CREATE TABLE new_foo LIKE foo;

RENAME TABLE foo TO old_foo, new_foo TO foo;

DROP TABLE old_foo;

Feito

Não foi possível você pegar o esquema remover a tabela e recriá-lo?

A melhor maneira que eu encontrei de fazer isso com o MySQL é:

DELETE from table_name LIMIT 1000;

Ou 10.000 (dependendo de quão rápido isso acontece).

Coloque isso em um loop até que todas as linhas são excluídas.

Por favor, tente isso, pois irá realmente funcionar. Vai levar algum tempo, mas ele vai trabalhar.

drop table deve ser o caminho mais rápido para se livrar dele.

Você já tentou usar "drop"? Eu usei-o em tabelas mais de 20GB e sempre termina em segundos.

Se você quiser apenas para se livrar da mesa completamente, porque não basta Queda isso?

truncar é rápido, geralmente na ordem de segundos ou menos. Se foram necessários 30 minutos, você provavelmente teve um caso de algumas chaves estrangeiras que fazem referência a tabela que foram truncar. Também pode haver questões envolvidas bloqueio.

truncar é eficaz como eficiente como se pode esvaziar uma tabela, mas você pode ter que remover as referências de chave estrangeira a menos que você quer que essas tabelas limpo também.

Nós tivemos esses problemas. Nós não usar o banco de dados como uma loja de sessão com Rails 2.x eo armazenamento de cookies. No entanto, eliminando a tabela é uma solução decente. Você pode querer considerar interromper o serviço mysql, registro de desativar temporariamente, começar as coisas em modo de segurança e, em seguida, fazer a sua queda / criar. Quando terminar, ligue o logging novamente.

Eu não tenho certeza por que está demorando tanto. Mas talvez tentar uma mudança de nome, e recriar uma tabela em branco. Depois, você pode remover a tabela "extra" sem se preocupar quanto tempo leva.

O searlea resposta é bom, mas como indicado nos comentários, você perde as chaves estrangeiras durante a luta. esta solução é semelhante: o truncamento é executado dentro de um segundo, mas você manter as chaves estrangeiras

.

O truque é que nós ativar / desativar as verificações FK.

SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
insert into NewFoo SELECT * from Foo where What_You_Want_To_Keep  

truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;

resposta Amplo - Apagar tudo, mas algumas linhas

Meu problema era: Por causa de um script louco, minha mesa era para com 7.000.000 linhas lixo. Eu precisava eliminar 99% dos dados nesta tabela , é por isso que eu precisava para copiar O que eu quero manter em uma tabela tmp antes deleteting.

Estas linhas Foo eu precisava manter estavam dependendo de outras mesas, que têm chaves estrangeiras e índices.

algo assim:

insert into NewFoo SELECT * from Foo where ID in (
 SELECT distinct FooID from TableA 
 union SELECT distinct FooID from TableB 
 union SELECT distinct FooID from TableC
)

mas esta consulta foi sempre o tempo limite após 1 hora. Então eu tive que fazê-lo como este:

CREATE TEMPORARY TABLE tmpFooIDS  ENGINE=MEMORY  AS (SELECT distinct FooID from TableA);
insert into tmpFooIDS SELECT distinct FooID from TableB
insert into tmpFooIDS SELECT distinct FooID from TableC
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);

teoria I, porque os índices estão configurados corretamente, eu acho que ambas as formas de preencher NewFoo deveria ter sido o mesmo, mas practicaly isso não aconteceu.

É por isso que, em alguns casos, você pode fazer assim:

SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;

-- Alternative way of keeping some data.
CREATE TEMPORARY TABLE tmpFooIDS  ENGINE=MEMORY  AS (SELECT * from Foo where What_You_Want_To_Keep);
insert into tmpFooIDS SELECT ID from Foo left join Bar where OtherStuff_You_Want_To_Keep_Using_Bar
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);

truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top