Come eliminare tabelle vuote


11

È possibile eliminare tutte le tabelle vuote dal mio enorme database (mysql)?

Sto cercando un comando sql per rimuovere automaticamente tutte quelle tabelle vuote.

Attualmente ho 305 tabelle nel mio set di dati e circa il 30% di esse sono vecchie tabelle vuote che non verranno utilizzate nella mia nuova applicazione.

Giusto per chiarire; Tutte le tabelle sono di tipo = MyISAM


1
Tutte le tabelle MyISAM, InnoDB o una combinazione di entrambe ???
RolandoMySQLDBA,

Sono tutti MyISAM
qualificati il

Risposte:


11

L'idea sarebbe probabilmente quella di cercare le tabelle vuote usando INFORMATION_SCHEMA.TABLES

SELECT * 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS =  '0'
AND TABLE_SCHEMA = 'my_database_only'

Quindi potresti essere in grado di produrre una query SQL con

SELECT CONCAT('DROP TABLE ', GROUP_CONCAT(table_name), ';') AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS = '0'
AND TABLE_SCHEMA = 'my_database_only';

Veloce e un po 'sporco, ma dovrebbe funzionare davvero.


3
... e quindi hai un server di database rotto perché hai "probabilmente" eliminato alcune delle tabelle di sistema mysql ... oltre al fatto che CONCAT produce un elenco di tabelle senza riferimento allo schema.
Cristian Porta,

1
Hai anche il "diritto" di aggiungere in modo intelligente le restrizioni del database alle tue tabelle, pensavo fosse ovvio.
Tom Desp,

3
la risposta non dovrebbe dare nulla per scontato perché le risposte sono potenzialmente pericolose per l'utente ... tutto qui
Cristian Porta

2
+1 per l'impostazione di un singolo comando DROP TABLE.
RolandoMySQLDBA,

1
@CP: Ok ho capito, mio ​​terribile errore, ecco perché ho modificato la risposta. A proposito, sono un po 'sorpreso che una query SQL possa effettivamente eliminare una tabella interna del sistema MySQL. Dal mio punto di vista, questo è totalmente rotto.
Tom Desp,

7

Poiché tutte le tabelle sono MyISAM, ciò rende la mia risposta più facile da esprimere.

Innanzitutto, è necessario eseguire una query di INFORMATION_SCHEMA per le tabelle che hanno zero righe:

SELECT table_schema,table_name FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

Quindi, formulare la query per eliminare le tabelle vuote:

SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

Ora, scarica i comandi in un file di testo SQL esterno.

SQL="SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand"
SQL="${SQL} FROM information_schema.tables WHERE table_rows = 0 AND table_schema"
SQL="${SQL} NOT IN ('information_schema','mysql','performance_schema')"
mysql -uroot -p -ANe"${SQL}" > DropTables.sql

Guarda i contenuti con uno dei seguenti

  • less DropTables.sql
  • cat DropTables.sql

Se sei soddisfatto del suo contenuto, esegui lo script:

mysql -uroot -p < DropTables.sql

o accedi a mysql ed eseguilo in questo modo:

mysql> source DropTables.sql

Provaci !!!

CAVEAT : questa tecnica funziona solo con la tabella MyISAM perché il conteggio delle righe di una tabella MyISAM è archiviato fisicamente nelle .MYDtabelle. La tabella dei metadati INFORMATION_SCHEMA.TABLES legge sempre questo e si aggiorna. NON PROVARE QUESTO CON INNODB !!!

AGGIORNAMENTO 2014-02-05 11:46 EST

C'è un motivo che ho escluso ('information_schema','mysql','performance_schema')

Lo mysqlschema contiene tabelle vuote al suo interno. Alcuni MyISAM, alcuni InnoDB, alcuni CSV.

Ad esempio, ecco le mie tabelle nello schema mysql per MySQL 5.6.15 sul mio desktop

mysql> select table_name,engine,table_rows
    -> from information_schema.tables
    -> where table_schema='mysql';
+---------------------------+--------+------------+
| table_name                | engine | table_rows |
+---------------------------+--------+------------+
| columns_priv              | MyISAM |          0 |
| db                        | MyISAM |          2 |
| event                     | MyISAM |          0 |
| func                      | MyISAM |          0 |
| general_log               | CSV    |          2 |
| help_category             | MyISAM |         40 |
| help_keyword              | MyISAM |        485 |
| help_relation             | MyISAM |       1090 |
| help_topic                | MyISAM |        534 |
| innodb_index_stats        | InnoDB |          0 |
| innodb_table_stats        | InnoDB |          0 |
| ndb_binlog_index          | MyISAM |          0 |
| plugin                    | MyISAM |          0 |
| proc                      | MyISAM |          0 |
| procs_priv                | MyISAM |          0 |
| proxies_priv              | MyISAM |          1 |
| servers                   | MyISAM |          0 |
| slave_master_info         | InnoDB |          0 |
| slave_relay_log_info      | InnoDB |          0 |
| slave_worker_info         | InnoDB |          0 |
| slow_log                  | CSV    |          2 |
| tables_priv               | MyISAM |          0 |
| time_zone                 | MyISAM |          0 |
| time_zone_leap_second     | MyISAM |          0 |
| time_zone_name            | MyISAM |          0 |
| time_zone_transition      | MyISAM |          0 |
| time_zone_transition_type | MyISAM |          0 |
| user                      | MyISAM |          6 |
+---------------------------+--------+------------+
28 rows in set (0.01 sec)

mysql>

Se alcuni di questi tavoli erano a scomparire (come columns_priv, proc_priv, tables_priv, etc.), il meccanismo di concessione potrebbe non funzionare correttamente o può causare mysqld non avviare. Inoltre, non vuoi colpire mysql.proc poiché è la sede fisica delle Stored Procedure. Altri meccanismi potrebbero non funzionare o se si desidera utilizzarli, come CrashSafe Replication utilizzando le tabelle InnoDB all'interno dello schema mysql o se si desidera inserire informazioni sul fuso orario.

AGGIORNAMENTO 2014-02-05 12:36 EST

Vorrei elogiare Tom Desp per la sua risposta per un motivo specifico: la sua sintassi potrebbe far cadere senza usare uno script esterno . Usando la sua idea, fammi acquisire il comando DROP TABLE in una variabile definita dall'utente.

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(DBTB),';')
INTO @DropCommand
FROM (SELECT CONCAT(table_schema,'.',table_name) DBTB
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema')) A;
SELECT @DropCommand;

Se l'output di SELECT @DropCommand;è corretto, quindi eseguire il comando in questo modo:

PREPARE s FROM @DropCommand;
EXECUTE s;
DEALLOCATE PREPARE s;

Questo elimina due cose:

  • la necessità di un file di testo SQL esterno
  • eseguendo un comando DROP TABLE separato per ogni tabella

1
Grazie per una spiegazione lunga e buona! +1 per la restituzione di tabelle in database. In questo modo è facile ripulire diversi set di dati. D'altro canto; usare con cura. Eseguo la tua query su "..AND table_schema = 'my_database_name'" per funzionare solo con un database (come suggerito da Tom Desp in un'altra risposta)
qualificato tra il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.