Boş tablolar nasıl bırakılır


11

Büyük veritabanımdan (mysql) tüm boş tabloları bırakmak mümkün mü?

Tüm bu boş tabloları otomatik olarak kaldırmak için bir sql komutu arıyorum.

Şu anda, veri kümemde 305 tablo var ve bunların yaklaşık% 30'u yeni uygulamamda kullanılmayacak olan eski boş tablolar.

Sadece netleştirmek için; Tüm tablolar = MyISAM türündedir


1
Tüm tablolar MyISAM, InnoDB veya her ikisinin bir karışımı mı ???
RolandoMySQLDBA

Hepsi MyISAM
Qualbeen

Yanıtlar:


11

Fikir muhtemelen kullanarak boş tabloları aramak olacaktır INFORMATION_SCHEMA.TABLES

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

Sonra ile bir SQL sorgusu üretmek mümkün olabilir

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

Hızlı ve biraz kirli, ama aslında çalışması gerekir.


3
... ve sonra kırık bir veritabanı sunucunuz çünkü "muhtemelen" bazı mysql sistem tablolarını sildiniz ... yanı sıra CONCAT şema başvurusu olmadan bir tablo listesi üretir.
Cristian Porta

1
Ayrıca akıllıca tablolarınıza veritabanı kısıtlamaları eklemek için "doğru" var, bunun açık olduğunu düşündüm.
Tom Desp

3
cevap verilen için hiçbir şey almamalıdır çünkü cevap potansiyel olarak kullanıcı için tehlikeli ... hepsi bu
Cristian Porta

2
Tek bir DROP TABLE komutu ayarlamak için +1.
RolandoMySQLDBA

1
@CP: Tamam, anlıyorum, korkunç hatam, bu yüzden cevabı düzenledim. Bu arada, bir SQL sorgusunun aslında bir MySQL sistemi iç tablosunu bırakabileceğine şaşırdım. Benim açımdan, bu tamamen kırılmış.
Tom Desp

8

Tüm tablolar MyISAM olduğundan cevabımı daha kolay ifade edebilirim.

İlk olarak, sıfır satır içeren tablolar için BİLGİ_SCHEMA sorgusunu sorgulamanız gerekir:

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

Ardından, boş tabloları bırakmak için sorguyu formüle edin:

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

Şimdi, komutları harici bir SQL metin dosyasına dökün.

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

İçeriğe aşağıdakilerden biriyle bakın

  • less DropTables.sql
  • cat DropTables.sql

İçeriğinden memnunsanız, komut dosyasını çalıştırın:

mysql -uroot -p < DropTables.sql

veya mysql'a giriş yapın ve şu şekilde çalıştırın:

mysql> source DropTables.sql

Bir şans ver !!!

CAVEAT : Bu teknik yalnızca MyISAM tablosuyla çalışır çünkü MyISAM tablosunun satır sayısı fiziksel .MYDolarak tabloların içinde saklanır . BİLGİ_SCHEMA.TABLES meta veri tablosu her zaman bunu okuyor ve güncelleniyor. INNODB İLE BUNU DENEMEYİN !!!

GÜNCELLEME 2014-02-05 11:46 EST

Hariç tutmamın bir nedeni var ('information_schema','mysql','performance_schema')

mysqlŞema içinde boş tablolar vardır. Bazıları MyISAM, bazıları InnoDB, bazıları CSV.

Örneğin, masaüstümde MySQL 5.6.15 için mysql şemasındaki tablolarım

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>

Bu tablolardan bazıları (gibi yok olsaydı columns_priv, proc_priv, tables_privvs.), hibe mekanizması düzgün çalışmayabilir veya mysqld'nin neden olabilir başlatmak için değil. Ayrıca saklı yordamlar fiziksel ev olduğu için mysql.proc vurmak istemiyorum. Mysql şemasının içindeki InnoDB tablolarını kullanarak CrashSafe Replication gibi veya kullanmak istediğinizde veya saat dilimi bilgileri eklemek istiyorsanız diğer mekanizmalar çalışmayabilir.

GÜNCELLEME 2014-02-05 12:36 EST

Tom Desp'e cevabını belirli bir nedenden ötürü övmek istiyorum : Sözdizimi harici bir komut dosyası kullanmadan düşüşü yapabilir . Fikrini kullanarak, DROP TABLE komutunu kullanıcı tanımlı bir değişkene yakalayayım.

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;

Eğer çıkışı SELECT @DropCommand;doğru ise, komutu şu şekilde yürütün:

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

Bu iki şeyi ortadan kaldırır:

  • harici bir SQL metin dosyası ihtiyacı
  • her tablo için ayrı bir DROP TABLE komutu çalıştırma

1
Uzun ve iyi bir açıklama için teşekkürler! Veritabanları arasında tablolar döndürmek için +1. Bu şekilde birkaç veri kümesini temizlemek kolaydır. Diğer yandan; dikkatli kullanın. Sorgunuzu yalnızca bir veritabanıyla (Tom
Desp'in
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.