빈 테이블을 삭제하는 방법


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
CONCAT가 스키마 참조없이 테이블 목록을 생성한다는 사실 외에도 mysql 시스템 테이블 중 일부를 "아마도"삭제했기 때문에 데이터베이스 서버가 손상되었습니다.
Cristian Porta

1
또한 테이블에 데이터베이스 제한을 스마트하게 추가 할 수있는 "권리"가 있다고 생각합니다.
Tom Desp

3
답변은 잠재적으로 사용자에게 위험하기 때문에 당연한 것으로 여겨서는 안됩니다 ... 그게 전부입니다
Cristian Porta

2
단일 DROP TABLE 명령을 설정하는 경우 +1
RolandoMySQLDBA

1
@CP : 알았어. 끔찍한 실수인데, 내가 답을 편집 한 이유야. 그건 그렇고, SQL 쿼리가 실제로 MySQL 시스템 내부 테이블을 삭제할 수 있다는 것에 약간 놀랐습니다. 내 관점에서 볼 때 그것은 완전히 깨졌습니다.
Tom Desp

7

모든 테이블은 MyISAM이므로 내 대답을 쉽게 표현할 수 있습니다.

먼저 행이 0 인 테이블에 대해 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, 일부 InnoDB, 일부 CSV.

예를 들어, 다음은 데스크탑의 MySQL 5.6.15에 대한 mysql 스키마의 테이블입니다.

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는 저장 프로 시저의 실제 홈이므로 whack하고 싶지 않습니다. mysql 스키마 내부의 InnoDB 테이블을 사용하는 CrashSafe 복제와 같은 다른 메커니즘이나 시간대 정보를 삽입하려는 경우 다른 메커니즘이 작동하지 않을 수 있습니다.

업데이트 2014-02-05 12:36 EST

구체적인 이유 때문에 Tom 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;

의 출력 SELECT @DropCommand;이 올바른 경우 다음과 같이 명령을 실행하십시오.

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

이것은 두 가지를 제거합니다.

  • 외부 SQL 텍스트 파일의 필요성
  • 각 테이블에 대해 별도의 DROP TABLE 명령 실행

1
길고 좋은 설명 감사합니다! 데이터베이스간에 테이블을 반환하는 경우 +1 이 방법으로 여러 데이터 세트를 쉽게 정리할 수 있습니다. 반면에; 주의해서 사용하십시오. "..AND table_schema = 'my_database_name'"에 대해 쿼리를 실행하여 하나의 데이터베이스에서만 작동합니다 (Tom
Desp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.