วิธีการวางตารางที่ว่างเปล่า


11

เป็นไปได้หรือไม่ที่จะลบตารางที่ว่างเปล่าทั้งหมดออกจากฐานข้อมูลขนาดใหญ่ของฉัน (mysql)?

ฉันกำลังมองหาคำสั่ง sql ที่จะลบตารางว่างเหล่านั้นทั้งหมดโดยอัตโนมัติ

ขณะนี้ฉันมี 305 ตารางในชุดข้อมูลของฉันและประมาณ 30% ของพวกเขาเป็นตารางเปล่าเก่าที่จะไม่ใช้ในแอปพลิเคชันใหม่ของฉัน

เพียงชี้แจง ตารางทั้งหมดเป็นประเภท = MyISAM


1
ทุกตาราง MyISAM, InnoDB หรือทั้งสองอย่างรวมกันหรือไม่?
RolandoMySQLDBA

พวกเขาทั้งหมดเป็น MyISAM
qualbeen

คำตอบ:


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 ของคุณสร้างรายการตารางโดยไม่มีการอ้างอิงสกีมา
Cristian Porta

1
คุณมี "สิทธิ" ในการเพิ่มข้อ จำกัด ฐานข้อมูลลงในตารางอย่างชาญฉลาดฉันคิดว่ามันชัดเจน
Tom Desp

3
คำตอบไม่ควรทำอะไรเลยเพราะคำตอบนี้อาจเป็นอันตรายต่อผู้ใช้ ... นั่นคือทั้งหมด
Cristian Porta

2
+1 สำหรับการตั้งค่าคำสั่ง DROP TABLE เดียว
RolandoMySQLDBA

1
@CP: ตกลงฉันเข้าใจแล้วความผิดพลาดอันยิ่งใหญ่ของฉันนั่นเป็นสาเหตุที่ฉันแก้ไขคำตอบ โดยวิธีการที่ฉันแปลกใจเล็กน้อยแบบสอบถาม SQL จริงสามารถวางตาราง MySQL ระบบภายใน จากมุมมองของฉันมันพังทลายหมด
Tom Desp

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

ให้มันลอง !!!

ถ้ำ : เทคนิคนี้ใช้ได้กับตาราง MyISAM เท่านั้นเนื่องจากจำนวนแถวของตาราง MyISAM จะถูกเก็บไว้ใน.MYDตาราง ตารางข้อมูลเมตา Information_SCHEMA.TABLES จะอ่านและอัปเดตอยู่เสมอ อย่าลองสิ่งนี้กับ INNODB !!!

อัพเดท 2014-02-05 11:46 EST

มีเหตุผลที่ฉันยกเว้น ('information_schema','mysql','performance_schema')

mysqlสคีมีโต๊ะว่างในนั้น บางคนMyISAMบางบางInnoDBCSV

ตัวอย่างเช่นนี่คือตารางของฉันใน schema 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ฯลฯ ) กลไกทุนอาจไม่ทำงานอย่างถูกต้องหรืออาจทำให้เกิด mysqld ไม่ได้ที่จะเริ่มต้นขึ้น คุณยังไม่ต้องการที่จะตี mysql.proc เพราะมันเป็นบ้านทางกายภาพของกระบวนงานที่เก็บไว้ กลไกอื่น ๆ อาจไม่ทำงานหากคุณต้องการใช้เช่น CrashSafe Replication โดยใช้ตาราง InnoDB ภายใน mysql schema หรือถ้าคุณต้องการแทรกข้อมูลเขตเวลา

อัปเดต 2014-02-05 12:36 EST

ผมอยากจะยกย่องทอม Desp สำหรับคำตอบของเขาสำหรับเหตุผลที่เฉพาะเจาะจง: ไวยากรณ์ของเขาสามารถทำอะไรได้ลดลงโดยไม่ต้องใช้สคริปต์ภายนอก ใช้ความคิดของเขาให้ฉันจับคำสั่ง 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;

หากเอาต์พุตของ the SELECT @DropCommand;นั้นถูกต้องให้รันคำสั่งดังนี้:

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

สิ่งนี้จะกำจัดสองสิ่ง:

  • ความต้องการไฟล์ข้อความ SQL ภายนอก
  • การรันคำสั่ง DROP TABLE แยกกันสำหรับแต่ละตาราง

1
ขอบคุณสำหรับคำอธิบายที่ยาวและดี! +1 สำหรับการส่งคืนตารางข้ามฐานข้อมูล วิธีนี้ง่ายต่อการล้างชุดข้อมูลหลายชุด ในทางกลับกัน; ใช้ด้วยความระมัดระวัง ฉันเรียกใช้แบบสอบถามของคุณกับ "..AND TABLE_SCHEMA = 'my_database_name" การทำงานเฉพาะกับฐานข้อมูลหนึ่ง (ทอม Desp ปัญหาในการตอบอื่น ๆ )
qualbeen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.