
현재 약 5,400만 개의 레코드를 포함하고 크기가 20GB인 MyISAM 테이블이 있습니다. 이 데이터베이스를 설계할 때 잘못된 선택을 했습니다. 저는 DB 전문가는 아니지만 이 테이블은 지속적으로 작성되고 쿼리되는 경우가 드물기 때문에 InnoDB가 더 나은 선택이었을 것 같습니다. 문제는 이 테이블이 거의 항상 쓰기 가능해야 한다는 것입니다. 필드 중 하나는 타임스탬프가 있는 필드입니다. 기록은 5년 전으로 거슬러 올라갑니다. 마지막 6개월만 보관하면 됩니다. 몇 가지 삭제를 시도했는데 테이블이 잠겨서 쓸 수 없는 200,000개의 행을 삭제하는 데 약 20분이 걸렸습니다. 몇 시간 동안 테이블을 잠그지 않고 이 테이블의 크기를 줄일 수 있는 방법에 대한 제안이 있는 사람이 있습니까? 불필요한 행을 삭제하는 더 빠른 방법이 있습니까? 저는 MyISAM 테이블을 InnoDB 테이블로 변환한 적이 없습니다. 이 과정이 오래 걸리나요?
답변1
나는 마침내 이 프로젝트를 다시 방문할 시간을 갖게 되었고 완전성을 위해 내가 하게 된 일을 게시하고 싶었습니다. DELETE FROM이 너무 오래 걸리는 원래 문제는 삭제할 행을 지정하는 방법과 관련이 있다고 생각합니다. 나는 다음과 비슷한 진술을 사용하고있었습니다.
DELETE FROM table WHERE starttime < 20150101 limit 200000;
시작 시간 필드는 실제로 DATETIME입니다. 나는 다음을 사용하여 새 테이블을 만들었습니다.
CREATE TABLE new_table LIKE existing_table;
그런 다음 새 테이블의 엔진을 변경합니다.
ALTER TABLE new_table ENGINE=InnoDB;
그런 다음 이름을 바꾸면
RENAME TABLE existing_table TO old_table, new_table TO existing_table;
그 후에는 이전 테이블에서 새 테이블로 6개월 분량의 데이터를 가져와야 했습니다.
INSERT INTO existing_table SELECT * FROM old_table WHERE starttime BETWEEN DATE_SUB(NOW(), INTERVAL 6 MONTH) AND NOW();
제안해주신 마틴님께 감사드립니다. 저는 serverfault를 처음 접했기 때문에 그의 의견을 어떻게 답변으로 표시할지 잘 모르겠습니다.
답변2
MyISAM은 SELECT에만 적합합니다. Innodb에는 별도의 READ 및 WRITE 대기열이 있습니다. 따라서 200,000개의 행을 삭제하면 테이블이 잠기지 않습니다. 테이블 잠금은 프로덕션과 관련하여 MyISAM의 가장 큰 제한 사항 중 하나입니다. InnoDB는 대부분의 용도에서 MyISAM보다 느리지만 더 나은 잠금 메커니즘으로 인해 특정 조건에서는 더 빠르게 수행될 수 있습니다. MyISAM은 삽입/업데이트가 실행되는 동안 읽기 위해 전체 테이블을 잠급니다. InnoDB는 행 수준 잠금을 수행할 수 있으므로 테이블에 대한 여러 동시 쓰기 및 읽기가 가능합니다.
http://kakadba.blogspot.in/2014/02/innodb-vs-myisam.html
MyISAM을 INNODB로 변환
테이블별로 하시면 됩니다
ALTER TABLE table_name ENGINE=InnoDB;
아니면 스크립트를 사용해 한 번에 모두 수행할 수도 있습니다.
https://stackoverflow.com/questions/3856435/how-to-convert-all-tables-from-myisam-into-innodb