Cara menjatuhkan tabel kosong

11

Apakah mungkin untuk menghapus semua tabel kosong dari basis data besar saya (mysql)?

Saya mencari perintah sql untuk secara otomatis menghapus semua tabel kosong itu.

Saat ini, saya memiliki 305 tabel di dataset saya, dan sekitar 30% di antaranya adalah tabel kosong lama, yang tidak akan digunakan dalam aplikasi baru saya.

Hanya untuk mengklarifikasi; Semua tabel bertipe = MyISAM

memenuhi syarat
sumber
1
Apakah semua tabel MyISAM, InnoDB, atau campuran keduanya ???
RolandoMySQLDBA
Mereka semua adalah MyISAM
qualbeen

Jawaban:

11

Idenya mungkin akan mencari menggunakan tabel kosong INFORMATION_SCHEMA.TABLES

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

Maka Anda mungkin dapat menghasilkan kueri SQL dengan

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

Cepat dan agak kotor, tetapi seharusnya benar-benar berfungsi.

Tom Desp
sumber
3
... dan kemudian Anda memiliki server database yang rusak karena Anda "mungkin" menghapus beberapa tabel sistem mysql ... selain fakta bahwa CONCAT Anda menghasilkan daftar tabel tanpa referensi skema.
Cristian Porta
1
Anda juga memiliki "hak" untuk secara pintar menambahkan batasan database ke tabel Anda, saya pikir itu sudah jelas.
Tom Desp
3
jawabannya tidak boleh dianggap remeh karena jawabannya berpotensi berbahaya bagi pengguna ... itu saja
Cristian Porta
2
+1 untuk menyiapkan perintah DROP TABLE tunggal.
RolandoMySQLDBA
1
@ CP: Ok saya mengerti, kesalahan besar saya, itu sebabnya saya mengedit jawabannya. Ngomong-ngomong, saya sedikit terkejut permintaan SQL sebenarnya bisa menjatuhkan tabel internal sistem MySQL. Dari sudut pandang saya, itu benar-benar rusak.
Tom Desp
7

Karena semua tabel adalah MyISAM, ini membuat jawaban saya lebih mudah untuk diungkapkan.

Pertama, Anda perlu meminta informasi kepada tabel yang memiliki nol baris: 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');

Selanjutnya, rumuskan kueri untuk menjatuhkan tabel kosong:

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

Sekarang, buang perintah ke file teks SQL eksternal.

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

Lihatlah isinya dengan salah satu dari yang berikut ini

  • less DropTables.sql
  • cat DropTables.sql

Jika Anda puas dengan isinya, jalankan skrip:

mysql -uroot -p < DropTables.sql

atau masuk ke mysql dan jalankan seperti ini:

mysql> source DropTables.sql

Cobalah !!!

CAVEAT : Teknik ini hanya bekerja dengan tabel MyISAM karena jumlah baris dari tabel MyISAM secara fisik disimpan di .MYDdalam tabel. Tabel metadata INFORMATION_SCHEMA.TABLES selalu membaca ini dan memperbarui. JANGAN MENCOBA DENGAN INNODB !!!

UPDATE 2014-02-05 11:46 EST

Ada alasan saya dikecualikan ('information_schema','mysql','performance_schema')

The mysqlSkema memiliki meja kosong di dalamnya. Beberapa MyISAM, beberapa InnoDB, beberapa CSV.

Sebagai contoh, berikut adalah tabel saya di skema mysql untuk MySQL 5.6.15 di desktop saya

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>

Jika beberapa dari mereka tabel menghilang (seperti columns_priv, proc_priv, tables_priv, dll), mekanisme hibah mungkin tidak bekerja dengan baik atau dapat menyebabkan mysqld tidak start up. Anda juga tidak ingin memukul mysql.proc karena ini adalah rumah fisik dari Stored Procedures. Mekanisme lain mungkin tidak berfungsi jika Anda ingin menggunakannya, seperti Replikasi CrashSafe menggunakan tabel InnoDB di dalam skema mysql, atau jika Anda ingin memasukkan informasi zona waktu.

UPDATE 2014-02-05 12:36 EST

Saya ingin memuji Tom Desp atas jawabannya karena alasan tertentu: Sintaksnya dapat melakukan drop tanpa menggunakan skrip eksternal . Menggunakan idenya, izinkan saya menangkap perintah DROP TABLE ke dalam variabel yang ditentukan pengguna.

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;

Jika output dari SELECT @DropCommand;sudah benar, maka jalankan perintah seperti ini:

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

Ini menghilangkan dua hal:

  • perlunya file teks SQL eksternal
  • menjalankan perintah DROP TABLE terpisah untuk setiap tabel
RolandoMySQLDBA
sumber
1
Terima kasih atas penjelasannya yang panjang dan bagus! +1 untuk mengembalikan tabel di seluruh basis data. Dengan cara ini, mudah untuk membersihkan beberapa dataset. Di samping itu; gunakan dengan hati-hati. Saya menjalankan kueri Anda terhadap "..AND table_schema = 'my_database_name'" untuk hanya bekerja dengan satu basis data (seperti yang disarankan Tom Desp dalam balasan lain)
qualbeen