2024. 3. 25. 21:48ㆍProject 해축갤/데이터베이스
배경
해축갤 프로젝트를 하며 데이터가 200만개에서 1억개로 늘어났을 때 게시물 조회 성능이 급격히 안 좋아져
쿼리 개선, title, content 기준 인덱스를 이것저것 넣어보며 실험을 하고 있었습니다.
인덱스중 title, content 2개를 가지고 B-Tree 인덱스를 생성하려 했다가 문제가 발생했습니다.
구체적인 상황 (like DB, 코드 구조)
해축갤의 게시글 테이블의 구조는 다음과 같습니다.
주의해서 봐야 하는 부분은 content 가 varchar(1000) 라는 겁니다.
제가 사용하는 MySQL 버전은 8.0.36 이고 입력한 명령어는 다음과 같습니다.
CREATE INDEX idx_title_content
ON post (title(100), content(100));
문제
위 쿼리를 실행하게 되면 다음과 같은 에러가 나오게 됩니다.
ERROR 1071 (42000): Specified key was too long;
max key length is 3072 bytes
즉, 인덱스로 넣을 수 있는 컬럼의 데이터 유형, 크기는 최대 3072 바이트라는것.
위에서 봤듯이 content 는 게시글의 내용이라 varchar(1000) 입니다.
String 이 8 byte 고 여기에 1000 을 곱하면 8 * 1,000 = 8,000 byte 입니다.
즉, content 가 길어서 문제가 되는 겁니다.
밑바탕 되는 기본 원리
- 인덱스는 데이터를 빨리 찾기 위한 자료구조이다.
- 그 목적은 데이터 검색시 디스크 접근 횟수를 줄이기.
- DBMS 는 크게 3가지 요인으로 인덱스를 메모리에 로딩한다.
1. 일반적으로 필요할 때 로딩.
2. 캐싱 / [[버퍼풀 메커니즘]] 사용 -> 자주 사용되는 인덱스는 MySQL 버퍼풀에 저장함!
3. 가용 가능한 메모리 등의 자원 상황에 따라 최적화
- 즉, 인덱스를 사용할땐 인덱스가 메모리에 올라가기에 무거우면 안된다.
- 인덱스에서 하나의 노드에 들어가는 키 값이 너무 크면 메모리에 인덱스를 전부 담을 수 없다.
- 이렇게 될 경우 메모리에 load 하지 못한 나머지는 디스크에서 조회해야 한다.
- 그래서 MySQL 은 기본값으로 3072 바이트로 인덱스 컬럼의 크기를 제한한다. (버전 별로 상이함!)
개선/해결 고민 및 선택
저는 다음과 같은 SQL 쿼리문으로 해결했습니다.
CREATE INDEX idx_title_content ON post (title, content(255));
위 쿼리는 title, content 에 대해서 인덱스를 생성하되,
content 에 대해서는 255 byte 까지만 인덱스의 키 값으로 두겠다는 것입니다.
이렇게 했던 이유는 해축갤의 비즈니스 특성 때문입니다.
다음은 해축갤의 검색 결과물입니다.
흥민이라고 검색했을 때 제목에 흥민이라는 키워드가 없는 게시물들이 존재합니다.
이런 글에 들어가보게 되면 다음과 같습니다.
제목에서 문장을 시작해, 곧바로 본주제에 대한 키워드를 말하며 문장을 마무리하는 식의 글이 많다는 것입니다.
즉 글 상단부에서 주제의 메인 키워드가 보통 있기 때문에 이런 결정을 내렸씁니다.
5. 결론
- 프로젝트 배경: 해축갤 프로젝트에서 데이터가 200만 개에서 1억 개로 증가하면서,
게시물 조회 성능이 급격히 저하됨.
- 문제 발생: title, content를 포함한 B-Tree 인덱스 생성 시도 중,
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes 오류 발생.
- 문제의 원인: content 컬럼의 데이터 타입이 varchar(1000)으로 설정되어 있어, 인덱스 키의 최대 길이를 초과함.
- 해결 방법:CREATE INDEX idx_title_content ON post (title, content(255)); 명령어를 사용하여 인덱스 생성.
content 컬럼에 대해서는 255 바이트까지만 인덱스의 키 값으로 설정.
- 해결 방법의 근거:해축갤의 검색 패턴과 게시물 내용 분석을 통해,
content의 상단 부분에 주요 키워드가 포함되어 있는 경우가 많음을 확인.
이에 따라 content의 일부만 인덱스에 포함시켜도 검색 효율성이 유지될 수 있음을 판단.
이 방법을 통해 인덱스의 크기 문제를 해결하고, 데이터베이스의 검색 성능을 개선할 수 있었습니다.
'Project 해축갤 > 데이터베이스' 카테고리의 다른 글
손흥민 결승골 후 데이터 폭증: 해축갤에서의 3가지 인덱스 전략 (5) | 2024.03.26 |
---|---|
실시간 MySQL 데이터 복구: Master-Slave 구성과 MHA로 완성하는 고가용성 백업 전략 (1) | 2024.03.04 |
MySQL 데이터베이스 복구 실패: 실험에서 배운 교훈과 데이터베이스 관리 전략 (5) | 2024.01.23 |