Как отбрасывать пустые таблицы


11

Можно ли удалить все пустые таблицы из моей огромной базы данных (mysql)?

Я ищу команду sql для автоматического удаления всех этих пустых таблиц.

В настоящее время у меня есть 305 таблиц в моем наборе данных, и около 30% из них - старые пустые таблицы, которые не будут использоваться в моем новом приложении.

Чтобы уточнить; Все таблицы имеют тип = MyISAM


1
Все ли таблицы MyISAM, InnoDB или смесь обоих ???
— RolandoMySQLDBA

Все они - MyISAM
— до

Ответы:


11

Идея, вероятно, будет искать пустые таблицы, используя INFORMATION_SCHEMA.TABLES

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

Тогда вы сможете создать SQL-запрос с

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

Быстро и немного грязно, но на самом деле должно работать.


3
... а затем у вас сломан сервер базы данных, потому что вы "вероятно" удалили некоторые из системных таблиц mysql ... кроме того факта, что ваш CONCAT создает список таблиц без ссылки на схему.
— Кристиан Порта

1
У вас также есть «право» разумно добавлять ограничения базы данных к вашим таблицам, я думал, что это очевидно.
— Том Десп

3
ответ не должен принимать что-либо как должное, потому что ответ потенциально опасен для пользователя ... вот и все
— Кристиан Порта

2
+1 за настройку одной команды DROP TABLE.
— RolandoMySQLDBA

1
@CP: Хорошо, я понял, моя ужасная ошибка, поэтому я отредактировал ответ. Кстати, я немного удивлен, что SQL-запрос может фактически удалить внутреннюю таблицу системы MySQL. С моей точки зрения, это полностью сломано.
— Том Десп

7

Поскольку все таблицы являются MyISAM, это облегчает мой ответ.

Сначала вам нужно запросить у INFORMATION_SCHEMA таблицы с нулевыми строками:

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

Далее, сформулируйте запрос, чтобы удалить пустые таблицы:

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

Теперь поместите команды во внешний текстовый файл SQL.

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

Посмотрите на содержимое с одним из следующих

  • less DropTables.sql
  • cat DropTables.sql

Если вас устраивает его содержимое, запустите скрипт:

mysql -uroot -p < DropTables.sql

или войдите в MySQL и запустите его так:

mysql> source DropTables.sql

Попробуйте!

CAVEAT : этот метод работает только с таблицей MyISAM, поскольку счетчик строк таблицы MyISAM физически хранится в .MYDтаблицах. Таблица метаданных INFORMATION_SCHEMA.TABLES всегда читает это и обновляет. НЕ ПЫТАЙТЕСЬ С INNODB !!!

ОБНОВЛЕНИЕ 2014-02-05 11:46 EST

Есть причина, по которой я исключил ('information_schema','mysql','performance_schema')

В mysqlсхеме есть пустые таблицы. Некоторые MyISAM, некоторые InnoDB, некоторые CSV.

Например, вот мои таблицы в схеме MySQL для MySQL 5.6.15 на моем рабочем столе

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>

Если некоторые из этих таблиц должны были исчезнуть (как columns_priv, proc_priv, tables_privи т.д.), механизм гранта не может работать неправильно или может привести к туздЫ не пускать. Вы также не хотите взломать mysql.proc, поскольку это физический дом хранимых процедур. Другие механизмы могут не работать, если вы захотите их использовать, например, CrashSafe Replication с использованием таблиц InnoDB внутри схемы mysql или если вы хотите вставить информацию о часовом поясе.

ОБНОВЛЕНИЕ 2014-02-05 12:36 EST

Я хотел бы поблагодарить Тома Деспа за его ответ по определенной причине: его синтаксис может выполнить отбрасывание без использования внешнего сценария . Используя его идею, позвольте мне записать команду DROP TABLE в пользовательскую переменную.

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;

Если выходные данные SELECT @DropCommand;правильные, выполните команду следующим образом:

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

Это устраняет две вещи:

  • необходимость внешнего текстового файла SQL
  • запуск отдельной команды DROP TABLE для каждой таблицы

1
Спасибо за длинное и хорошее объяснение! +1 за возврат таблиц по базам данных. Таким образом, легко очистить несколько наборов данных. С другой стороны; используйте с осторожностью. Я запускаю ваш запрос к "..AND table_schema = 'my_database_name'", чтобы работать только с одной базой данных (как предложил Том Десп в другом ответе)
— задано
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.