i.am.developer

Timestamp를 PK로 쓰는건 피하자 본문

프로그래밍/트러블슈팅

Timestamp를 PK로 쓰는건 피하자

jongwow 2021. 3. 25. 01:12

문제

클루 서비스에서 글을 작성하는 API가 성능이 너무 안좋았다. 응답시간이 짧을때도 있지만 늦을때는 9초까지 걸렸다.

원인

글을 작성하면 성과로 Point를 주는데, 그와 관련된 Logging을 PointLog 테이블에 저장하도록 설정해두었음. 문제는 이 PointLog 테이블의 Primary Key가 Timestamp로 설정하고 있던 것!

timestamp를 primary key로 설정하는 것에 대한 의견1, 의견2.

해결

Primary Key를 따로 AutoIncrement한 값으로 설정해야했다. 생각해보면 어차피 로깅을 목적으로 하는 값이니까 GeneratedValue 로 해도 괜찮을텐데 왜 이렇게 했었을까.

 

조금 어려웠던 건 운영중인 서비스에 대해서 Table 스키마를 바꾸는거라 어떻게해야할지 조금 복잡했다.

 

대충 찾아보고 맘에드는 방법이 없어서 Table 갈아끼우기 방법으로 했다. 현재 서비스에 대한 Table을 "point_log"라고 한다면 이와 똑같은 Table, "point_log_2"를 생성하고 point_log_2의 스키마를 바꾼 뒤 API서버가 point_log_2를 바라보도록 수정했다. 그리고 point_log 테이블을 삭제하고 사용자가 없을 때 point_log_2의 이름을 point_log로 개명했다.

테이블 스키마를 바꾸는 DDL은 아래와 같았다.

 

제약조건 없애고
pk 삭제하고
//=====================================//
ALTER TABLE point_logs2 DROP CONSTRAINT point_logs2_ibfk_1

ALTER TABLE point_logs2 DROP PRIMARY KEY;

//=====================================//

point_log_id 추가하고
값입력하고
point_log_id를 pk로 만들고'

//=====================================//
ALTER TABLE point_logs2 ADD COLUMN point_log_id INT NOT NULL;
SET @X = 0;
UPDATE point_logs2 SET point_log_id = (@X:=@X+1) ORDER BY created_at ASC;
ALTER TABLE point_logs2 ADD PRIMARY KEY point_log_id (point_log_id);
ALTER TABLE point_logs2 CHANGE point_log_id point_log_id INT NOT NULL AUTO_INCREMENT;

//=====================================//

제약조건 다시 넣고

//===========================================//

ALTER TABLE point_logs2 ADD CONSTRAINT `FK_point_log_to_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON UPDATE NO ACTION ON DELETE NO ACTION

결과

그냥 처음에 DB를 설계할 때 잘하면 이런일도 없을텐데 바보같다. 그리고 Table을 갈아끼우는 방법이 너무 주먹구구식, 무식한 방법인 것 같아보인다.