Як скинути порожні таблиці


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
відповідь не повинна сприймати нічого як належне, оскільки відповідь потенційно небезпечна для користувача ... це все
Cristian Porta

2
+1 для налаштування однієї команди DROP TABLE.
RolandoMySQLDBA

1
@CP: Добре, я розумію, моя жахлива помилка, тому я відредагував відповідь. До речі, я трохи здивований, що запит SQL може насправді випустити внутрішню таблицю системи MySQL. З моєї точки зору, це повністю порушено.
Том Десп

8

Оскільки всі таблиці є 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 завжди читає це і оновлюється. НЕ СТІЙТЕ ЦЕ З ІННОДБОМ !!!

ОНОВЛЕННЯ 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'", щоб працювати тільки з однією базою даних (як Том Депп запропонував в іншій відповіді)
kvalenen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.