So löschen Sie leere Tabellen

11

Ist es möglich, alle leeren Tabellen aus meiner riesigen Datenbank (MySQL) zu löschen?

Ich suche nach einem SQL-Befehl, um alle diese leeren Tabellen automatisch zu entfernen.

Derzeit habe ich 305 Tabellen in meinem Datensatz, und ungefähr 30% davon sind alte leere Tabellen, die in meiner neuen Anwendung nicht verwendet werden.

Nur um klarzustellen; Alle Tabellen sind vom Typ = MyISAM

qualbeen
quelle
1
Sind alle Tabellen MyISAM, InnoDB oder eine Mischung aus beiden ???
RolandoMySQLDBA
Sie sind alle MyISAM
qualbeen

Antworten:

11

Die Idee wäre wahrscheinlich, mit nach den leeren Tabellen zu suchen INFORMATION_SCHEMA.TABLES

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

Dann können Sie möglicherweise eine SQL-Abfrage mit erstellen

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

Schnell und etwas schmutzig, sollte aber eigentlich funktionieren.

Tom Desp
quelle
3
... und dann haben Sie einen kaputten Datenbankserver, weil Sie "wahrscheinlich" einige der MySQL-Systemtabellen gelöscht haben ... abgesehen von der Tatsache, dass Ihr CONCAT eine Tabellenliste ohne Schema-Referenz erstellt.
Cristian Porta
1
Sie haben auch das "Recht", Ihren Tabellen intelligent Datenbankbeschränkungen hinzuzufügen. Ich dachte, das wäre offensichtlich.
Tom Desp
2
Die Antwort sollte nicht selbstverständlich sein, da die Antwort für den Benutzer möglicherweise gefährlich ist ... das ist alles
Cristian Porta
2
+1 zum Einrichten eines einzelnen DROP TABLE-Befehls.
RolandoMySQLDBA
1
@CP: Ok, ich verstehe, mein schrecklicher Fehler, deshalb habe ich die Antwort bearbeitet. Ich bin übrigens ein bisschen überrascht, dass eine SQL-Abfrage tatsächlich eine interne MySQL-Systemtabelle löschen könnte. Aus meiner Sicht ist das total kaputt.
Tom Desp
7

Da alle Tabellen MyISAM sind, ist meine Antwort leichter auszudrücken.

Zunächst müssen Sie INFORMATION_SCHEMA nach Tabellen mit null Zeilen abfragen:

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

Formulieren Sie als Nächstes die Abfrage, um die leeren Tabellen zu löschen:

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');

Speichern Sie nun die Befehle in einer externen SQL-Textdatei.

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

Schauen Sie sich den Inhalt mit einer der folgenden Möglichkeiten an

  • less DropTables.sql
  • cat DropTables.sql

Wenn Sie mit dem Inhalt zufrieden sind, führen Sie das Skript aus:

mysql -uroot -p < DropTables.sql

oder melden Sie sich bei MySQL an und führen Sie es folgendermaßen aus:

mysql> source DropTables.sql

Versuche es !!!

CAVEAT : Diese Technik funktioniert nur mit der MyISAM-Tabelle, da die Zeilenanzahl einer MyISAM-Tabelle physisch in der Tabelle gespeichert ist .MYD. Die Metadatentabelle INFORMATION_SCHEMA.TABLES liest dies immer und wird aktualisiert. VERSUCHEN SIE DAS NICHT MIT INNODB !!!

UPDATE 05.02.2014 11:46 EST

Es gibt einen Grund, den ich ausgeschlossen habe ('information_schema','mysql','performance_schema')

Das mysqlSchema enthält leere Tabellen. Einige MyISAM, einige InnoDB, einige CSV.

Hier sind zum Beispiel meine Tabellen im MySQL-Schema für MySQL 5.6.15 auf meinem 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>

Wenn einige dieser Tabellen verschwinden würden (wie columns_priv, proc_priv, tables_privusw.), arbeitet die Gewährung Mechanismus möglicherweise nicht richtig oder verursachen kann mysqld nicht zu starten. Sie möchten auch mysql.proc nicht schlagen, da es die physische Heimat von gespeicherten Prozeduren ist. Andere Mechanismen funktionieren möglicherweise auch nicht, wenn Sie sie verwenden möchten, z. B. CrashSafe Replication mithilfe der InnoDB-Tabellen im MySQL-Schema, oder wenn Sie Zeitzoneninformationen einfügen möchten.

UPDATE 05.02.2014 12:36 EST

Ich möchte Tom Desp aus einem bestimmten Grund für seine Antwort loben: Seine Syntax könnte das Löschen ohne Verwendung eines externen Skripts durchführen . Lassen Sie mich anhand seiner Idee den Befehl DROP TABLE in einer benutzerdefinierten Variablen erfassen.

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;

Wenn die Ausgabe von SELECT @DropCommand;korrekt ist, führen Sie den folgenden Befehl aus:

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

Dies eliminiert zwei Dinge:

  • die Notwendigkeit einer externen SQL-Textdatei
  • Ausführen eines separaten Befehls DROP TABLE für jede Tabelle
RolandoMySQLDBA
quelle
1
Vielen Dank für eine lange und gute Erklärung! +1 für die Rückgabe von Tabellen über Datenbanken hinweg. Auf diese Weise ist es einfach, mehrere Datensätze zu bereinigen. Auf der anderen Seite; Vorsichtig verwenden. Ich führe Ihre Abfrage gegen "..AND table_schema = 'my_database_name'" aus, um nur mit einer Datenbank zu arbeiten (wie Tom Desp in einer anderen Antwort vorgeschlagen hat)
qualbeen