Cómo soltar tablas vacías

11

¿Es posible eliminar todas las tablas vacías de mi enorme base de datos (mysql)?

Estoy buscando un comando sql para eliminar automáticamente todas esas tablas vacías.

Actualmente, tengo 305 tablas en mi conjunto de datos, y alrededor del 30% de ellas son tablas vacías viejas, que no se usarán en mi nueva aplicación.

Solo para aclarar; Todas las tablas son de tipo = MyISAM

Qualbeen
fuente
1
¿Son todas las tablas MyISAM, InnoDB o una mezcla de ambas?
RolandoMySQLDBA
Todos son MyISAM
calificados

Respuestas:

11

La idea probablemente sería buscar las tablas vacías usando INFORMATION_SCHEMA.TABLES

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

Entonces es posible que pueda generar una consulta 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';

Rápido y un poco sucio, pero en realidad debería funcionar.

Tom Desp
fuente
3
... y luego tiene un servidor de base de datos roto porque "probablemente" ha eliminado algunas de las tablas del sistema mysql ... además del hecho de que su CONCAT produce una lista de tablas sin referencia de esquema.
Cristian Porta
1
También tiene el "derecho" de agregar de manera inteligente restricciones de base de datos a sus tablas, pensé que era obvio.
Tom Desp
3
la respuesta no debe dar nada por sentado porque las respuestas son potencialmente peligrosas para el usuario ... eso es todo
Cristian Porta
2
+1 para configurar un solo comando DROP TABLE.
RolandoMySQLDBA
1
@CP: Ok, lo entiendo, mi terrible error, por eso edité la respuesta. Por cierto, estoy un poco sorprendido de que una consulta SQL realmente pueda eliminar una tabla interna del sistema MySQL. Desde mi perspectiva, eso está totalmente roto.
Tom Desp
7

Como todas las tablas son MyISAM, esto hace que mi respuesta sea más fácil de expresar.

Primero, necesita consultar el INFORMATION_SCHEMA para las tablas que tienen cero filas:

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

A continuación, formule la consulta para descartar las tablas vacías:

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

Ahora, volcar los comandos en un archivo de texto SQL externo.

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

Mire los contenidos con uno de los siguientes

  • less DropTables.sql
  • cat DropTables.sql

Si está satisfecho con su contenido, ejecute el script:

mysql -uroot -p < DropTables.sql

o inicie sesión en mysql y ejecútelo así:

mysql> source DropTables.sql

Darle una oportunidad !!!

PRECAUCIÓN : esta técnica solo funciona con la tabla MyISAM porque el recuento de filas de una tabla MyISAM se almacena físicamente en .MYDla tabla. La tabla de metadatos INFORMATION_SCHEMA.TABLES siempre está leyendo esto y actualizándose. ¡NO INTENTE ESTO CON INNODB!

ACTUALIZACIÓN 2014-02-05 11:46 EST

Hay una razón por la que excluí ('information_schema','mysql','performance_schema')

El mysqlesquema tiene tablas vacías. Algunos MyISAM, algunos InnoDB, algunos CSV.

Por ejemplo, aquí están mis tablas en el esquema mysql para MySQL 5.6.15 en mi escritorio

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>

Si algunas de esas mesas estaban a desaparecer (como columns_priv, proc_priv, tables_priv, etc.), el mecanismo de donaciones no funcione correctamente o puede hacer que mysqld no se inicie. Usted no quiere golpear mysql.proc ya que es el hogar físico de los procedimientos almacenados. Es posible que otros mecanismos no funcionen si desea usarlos, como la replicación CrashSafe usando las tablas InnoDB dentro del esquema mysql, o si desea insertar información de zona horaria.

ACTUALIZACIÓN 2014-02-05 12:36 EST

Me gustaría felicitar a Tom Desp por su respuesta por una razón específica: su sintaxis podría eliminar sin usar un script externo . Usando su idea, permítanme capturar el comando DROP TABLE en una variable definida por el usuario.

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;

Si la salida de la SELECT @DropCommand;es correcta, ejecute el comando de esta manera:

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

Esto elimina dos cosas:

  • la necesidad de un archivo de texto SQL externo
  • ejecutar un comando DROP TABLE separado para cada tabla
RolandoMySQLDBA
fuente
1
Gracias por una larga y buena explicación! +1 para devolver tablas en bases de datos. De esta manera, es fácil limpiar varios conjuntos de datos. Por otra parte; Usar con cuidado. Ejecuté su consulta contra "..AND table_schema = 'my_database_name'" para trabajar solo con una base de datos (como sugirió Tom Desp en otra respuesta)
calificó