테마
클러스터링·AHI·엔진 비교
아키텍처 관점에서 InnoDB를 마무리한다. PK(Primary Key, 기본 키) 순서로 행을 저장하는 클러스터링, 외래 키(foreign key) 지원, AHI(Adaptive Hash Index, 적응형 해시 인덱스), 엔진 비교표를 다룬다.
PK 클러스터링과 외래 키
- InnoDB 테이블은 행을 PK 순서로 정렬해 저장한다. 행 데이터 자체가 PK 인덱스 안에 들어 있는 이 구조를 클러스터링 인덱스(clustered index)라 한다(자세히는 클러스터링 인덱스 문서). 아키텍처 관점에서 기억할 건 테이블과 인덱스가 한 몸이라는 점이다.
- 외래 키는 테이블 정의에 선언하는 제약 조건(constraint)이다. 선언은 서버 층이 받고, 실제로 지키게 만드는 일은 InnoDB가 한다. MyISAM은 선언을 문법으로 읽기만(파싱) 하고 무시한다. 그래서 엔진을 바꾸면 제약이 에러 없이 조용히 사라진다는 함정이 있다.
- 클러스터링이 아닌 엔진(MyISAM·MEMORY)은 행을 순서 없이 쌓는 힙(heap)1 저장에 인덱스를 따로 둔다.
어댑티브 해시 인덱스(AHI)
InnoDB는 자주 접근하는 B-Tree 페이지(page)를 자동으로 해시화해 메모리에 올린다. 해시는 키 값으로 위치를 바로 계산해 찾는 구조다. 그래서 =로 값 하나를 찾는 동등 조회가 B-Tree를 위에서부터 타고 내려가는 대신 해시 한 번으로 끝나 빠르다.
- 자동이라 DBA(Database Administrator, 데이터베이스 관리자)가 만들지 않는다.
innodb_adaptive_hash_index로 끄고 켤 수 있다. - MySQL 8.4에서는 기본값이 OFF다(8.4 이전에는 기본 ON). 업그레이드 후 성능 차이를 볼 때 이 기본값 변경을 확인한다.
- 읽기가 많고 동등 조회 위주인 부하에서 효과가 있다. 범위 스캔 위주면 소용없다.
- 경합이 심하면 오히려 병목이 된다. 여러 스레드가 AHI를 보호하는 래치(latch)를 서로 잡으려고 기다리기 때문이다. 이때는
innodb_adaptive_hash_index_parts로 AHI를 여러 조각(파티션)으로 나누거나 끈다.
면접 한 줄: "자주 타는 B-Tree 경로를 서버가 알아서 해시로 지름길 내는 것."
엔진 비교
표의 트랜잭션(transaction)은 여러 작업을 한 묶음으로 확정하거나 취소하는 기능이다. OLTP(Online Transaction Processing, 온라인 트랜잭션 처리)는 주문·결제처럼 짧은 읽기·쓰기가 많이 몰리는 업무를 말한다.
| InnoDB | MyISAM | MEMORY | |
|---|---|---|---|
| 트랜잭션 | ◯ | ✕ | ✕ |
| 잠금 | 행 | 테이블 | 테이블 |
| 외래 키 | 강제 | 무시 | ✕ |
| 저장 | 클러스터링 | 힙+인덱스 | 메모리 해시·B-Tree |
| 용도 | 기본값·OLTP | 읽기 전용·임시 | 세션·캐시 테이블 |
기본 선택은 InnoDB다. MyISAM은 기존 시스템 호환처럼 제한된 상황에서만 검토하고, MEMORY는 재시작 시 사라져도 되는 작은 작업 테이블에 적합하다. 엔진은 테이블마다 지정할 수 있다. 하지만 한 트랜잭션 안에서 MyISAM 같은 비트랜잭션 엔진을 섞으면 원자성(atomicity)이 깨진다. 트랜잭션을 취소하는 롤백(rollback)을 해도 MyISAM 쪽 변경은 되돌려지지 않기 때문이다.
면접 포인트
- "AHI가 뭐예요?" → 자동 해시 지름길. DBA가 만드는 게 아니라는 점.
- "MyISAM에 외래 키를 선언하면?" → 파싱만 하고 무시. 조용히 안 지켜진다.
- "엔진을 섞으면?" → 트랜잭션 경계가 무너진다. 전부 InnoDB가 원칙.
참고
행을 정렬하지 않고 빈자리에 쌓아 두는 저장 방식. 인덱스는 따로 만들고, 인덱스가 행이 있는 위치를 가리킨다. ↩︎
