MySQL 미드레벨 CS 기초 면접
새 면접Q. MySQL InnoDB에서 인덱스로 사용되는 B+Tree와 Hash 자료구조의 특징을 비교하고, 왜 InnoDB는 기본 인덱스로 B+Tree를 선택했는지 범위 검색, 정렬, 메모리 효율성 관점에서 설명해주세요.
B+Tree는 모든 데이터가 리프 노드에 정렬되어 있고 리프 노드끼리 연결되어 있어 범위 검색(BETWEEN, >, <)과 ORDER BY에 효율적입니다. Hash는 O(1)의 등호 검색 성능을 제공하지만 범위 검색이 불가능하고 정렬을 지원하지 않습니다. InnoDB는 OLTP 환경에서 범위 검색과 정렬이 빈번하고, B+Tree가 디스크 I/O를 최소화하는 구조이기 때문에 B+Tree를 기본으로 선택했습니다. Hash 인덱스는 Memory 스토리지 엔진에서 제한적으로 사용되며, InnoDB는 내부적으로 Adaptive Hash Index를 자동으로 생성하여 자주 접근하는 페이지에 대해서만 Hash를 활용합니다.
- • B+Tree는 리프 노드가 연결되어 범위 검색과 정렬에 효율적
- • Hash는 등호 검색만 O(1)이고 범위 검색 불가능
- • InnoDB는 OLTP 특성상 범위 검색이 빈번하여 B+Tree 선택
- • Adaptive Hash Index로 자주 사용되는 데이터는 Hash로 자동 최적화
B+Tree의 높이가 성능에 미치는 영향과, 인덱스 키의 크기가 B+Tree 높이에 어떤 영향을 주는지 설명해주세요.
Q. MySQL에서 Optimistic Lock과 Pessimistic Lock의 동작 원리와 구현 방법을 설명하고, 전자상거래 시스템에서 한정 수량 상품 구매 시나리오에서 각 방식의 적합성과 트레이드오프를 설명해주세요.
Pessimistic Lock은 SELECT ... FOR UPDATE를 사용하여 조회 시점에 행 락을 획득하고 트랜잭션 종료까지 유지하여 다른 트랜잭션의 접근을 차단합니다. Optimistic Lock은 version 컬럼을 두고 UPDATE 시 WHERE 조건에 version을 포함하여, 변경이 없을 때만 업데이트하고 실패 시 재시도합니다. 한정 수량 상품의 경우 동시 구매 충돌이 빈번하므로 Pessimistic Lock이 더 적합합니다. Optimistic Lock은 충돌 시 재시도 로직이 복잡하고 사용자 경험이 저하될 수 있지만, 읽기가 많고 쓰기 충돌이 적은 환경에서는 락 대기 시간이 없어 효율적입니다. 재고 차감처럼 충돌이 예상되는 경우 Pessimistic Lock으로 데이터 정합성을 보장하는 것이 실무적입니다.
- • Pessimistic Lock은 SELECT FOR UPDATE로 선점적 락, 충돌 방지
- • Optimistic Lock은 version 컬럼으로 업데이트 시점 검증, 충돌 시 재시도
- • 한정 수량 상품은 충돌이 빈번하므로 Pessimistic Lock이 적합
- • Optimistic Lock은 읽기 위주 환경에서 락 오버헤드 감소
Pessimistic Lock을 사용할 때 데드락을 방지하기 위한 락 획득 순서 전략과, 타임아웃 설정의 중요성을 설명해주세요.
Q. MySQL에서 JOIN 알고리즘인 Nested Loop Join, Block Nested Loop Join, Hash Join의 동작 원리와 각각의 성능 특성을 설명하고, MySQL 8.0에서 Hash Join이 추가된 배경을 설명해주세요.
Nested Loop Join은 외부 테이블의 각 행마다 내부 테이블을 반복 스캔하는 방식으로, 내부 테이블에 인덱스가 있으면 효율적이지만 없으면 비효율적입니다. Block Nested Loop Join은 외부 테이블의 여러 행을 Join Buffer에 저장하고 내부 테이블을 한 번 스캔하면서 매칭하여, 인덱스가 없을 때 반복 스캔을 줄입니다. Hash Join은 작은 테이블로 해시 테이블을 만들고 큰 테이블을 스캔하며 O(1)로 매칭하는 방식으로, 등호 조인에서 인덱스 없이도 매우 빠릅니다. MySQL 8.0.18부터 Hash Join이 추가되어 인덱스가 없는 대용량 테이블 간 조인 성능이 크게 개선되었으며, 특히 분석 쿼리와 배치 작업에서 효과적입니다.
- • Nested Loop는 인덱스 기반 조인에 효율적, 인덱스 없으면 비효율
- • Block Nested Loop는 Join Buffer로 반복 스캔 최소화
- • Hash Join은 해시 테이블로 인덱스 없이도 빠른 등호 조인
- • MySQL 8.0에서 Hash Join 추가로 분석 쿼리 성능 향상
join_buffer_size 파라미터가 Block Nested Loop Join 성능에 미치는 영향과, 적절한 크기를 결정하는 방법을 설명해주세요.
Q. InnoDB의 클러스터드 인덱스(Clustered Index)와 세컨더리 인덱스(Secondary Index)의 물리적 저장 구조 차이를 설명하고, 세컨더리 인덱스로 조회할 때 발생하는 추가 비용과 이를 최소화하는 방법을 설명해주세요.
클러스터드 인덱스는 Primary Key 순서로 실제 데이터 행을 물리적으로 저장하는 인덱스로, 리프 노드에 전체 행 데이터가 포함됩니다. 세컨더리 인덱스는 인덱스 키와 Primary Key 값만 저장하며, 리프 노드에서 Primary Key를 얻은 후 클러스터드 인덱스를 다시 탐색해야 실제 데이터를 조회할 수 있습니다. 이 과정을 북마크 룩업(Bookmark Lookup)이라 하며, 추가 I/O가 발생하여 성능이 저하됩니다. 이를 최소화하려면 Covering Index를 활용하여 필요한 컬럼을 인덱스에 포함시키거나, Primary Key를 작게 유지하여 세컨더리 인덱스 크기를 줄이고, WHERE와 SELECT 컬럼을 최소화해야 합니다.
- • 클러스터드 인덱스는 PK 순서로 실제 데이터를 물리적 저장
- • 세컨더리 인덱스는 인덱스 키 + PK만 저장
- • 세컨더리 인덱스 조회 시 PK로 클러스터드 인덱스 재탐색 필요
- • Covering Index와 작은 PK로 북마크 룩업 비용 최소화
Primary Key로 AUTO_INCREMENT INT를 사용하는 것과 UUID를 사용하는 것의 차이점을, 인덱스 구조와 삽입 성능 관점에서 설명해주세요.
Q. MySQL 서버의 메모리 사용 구조를 Global Buffer와 Session Buffer로 구분하여 설명하고, OOM(Out Of Memory) 발생을 방지하기 위한 메모리 파라미터 설정 전략을 설명해주세요.
Global Buffer는 모든 세션이 공유하는 메모리로 innodb_buffer_pool_size(데이터/인덱스 캐시), innodb_log_buffer_size(리두 로그), key_buffer_size(MyISAM 인덱스) 등이 있습니다. Session Buffer는 각 커넥션마다 할당되는 메모리로 sort_buffer_size, join_buffer_size, read_buffer_size 등이 있으며, 커넥션 수에 비례하여 증가합니다. OOM을 방지하려면 innodb_buffer_pool_size를 전체 메모리의 70-80%로 설정하고, max_connections × (session buffer 합계)를 고려하여 여유 메모리를 확보해야 합니다. Session Buffer는 기본값을 유지하고 필요시에만 증가시키며, Connection Pool 크기를 적절히 제한하여 동시 커넥션 수를 관리해야 합니다.
- • Global Buffer는 공유 메모리, Session Buffer는 커넥션당 할당
- • innodb_buffer_pool_size가 가장 큰 메모리 사용 영역
- • 총 메모리 = Global + (Session × max_connections) + OS 여유분
- • Connection Pool 제한과 Session Buffer 최소화로 OOM 방지
innodb_buffer_pool_size를 동적으로 변경할 때 발생하는 성능 영향과, 변경 작업을 안전하게 수행하는 방법을 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!