[데이터베이스] 인덱스 접근방식

dev_hwan·2023년 8월 23일
1

얼마전에 면접에서 랜덤엑세스에 대하여 질문을 받았습니다.

혹시 쿼리 실행계획 분석을 해보셨다고 하셨는데 랜덤액세스에 대해서 설명해주실 수 있나요?

이전에 원티드에서 진행한 프리온보딩 MySQL편에서 지나가다 얼핏 그런 단어를 들어본 경험이 있었지만 자세하게 생각이 나질 않아 잘 모른다고 대답을 하였습니다.

기존에 explain을 사용해서 쿼리튜닝을 해본 경험은 slow query가 발생하는 지 확인학고 full scan인지 인덱스를 활용하는지 확인을 했던 정도로만 활용해 보며 크게 고려하지 않았었습니다.

따라서, 오늘은 인덱스의 접근 방식인 랜덤 액세스순차 액세스에 대해서 정리해 보려고 합니다.

1. MySQL의 인덱스 구조

가장 일반적으로 사용하는 MySQL 8.0의 InnoDB 기준으로 인덱스의 자료구조는 B+Tree를 사용하고 있습니다.

InnoDB 인덱스의 물리적 구조

B+tree에 대해서는 여기서는 간단하게 만 설명하고 넘어 가려고 합니다.

B-Tree 구조에 대한 이해

  • B+tree
    • B-Tree의 변형된 형태로, B-Tree와 달리 모든 값들이 리프 노드에만 저장됩니다. 이는 디스크 I/O 연산을 최소화하게 해주며, B-Tree보다 탐색 속도가 빠르다는 장점이 있습니다.
    • B+Tree에서는 리프 노드끼리 연결된 링크가 있어서, 순차적인 접근에 유리합니다.
    • B+Tree의 시간복잡도는 O(logN) 입니다.

2. 순차 액세스

순차 액세스란 데이터를 처음부터 끝까지 순서대로 접근하는 방식을 말합니다. 주로 테이블의 풀 스캔이나 인덱스의 리프 노드를 처음부터 끝까지 탐색할 때 사용됩니다. 순차 액세스는 대량의 데이터를 연속적으로 읽을 때 빠르지만, 특정 데이터를 찾기 위해서는 많은 데이터를 순차적으로 읽어야 하므로 비효율적일 수 있습니다.

3. 랜덤 액세스

랜덤 액세스란, 데이터의 위치와 상관없이 특정 데이터에 직접 접근하는 방식을 말합니다. B+Tree와 같은 인덱스 구조를 사용하면, 디스크 상의 어떤 위치에 있는 데이터라도 로그 시간 내에 접근할 수 있습니다. 랜덤 액세스는 필요한 데이터만 효율적으로 가져올 수 있어서, 특정 행을 조회하거나 조건에 맞는 데이터를 빠르게 찾을 때 매우 유용합니다.

그러나, 랜덤 액세스는 디스크 I/O 연산을 여러 번 수행해야 할 수 있기 때문에, 데이터를 연속적으로 읽어야 할 때는 순차 액세스보다 느릴 수 있습니다.

요약하면, 랜덤 액세스는 특정 데이터를 빠르게 찾을 때 유용하며, 순차 액세스는 대량의 데이터를 연속적으로 읽을 때 유용합니다. MySQL의 인덱스는 B+Tree 구조를 사용하여 랜덤 액세스의 효율성을 극대화하고, 동시에 리프 노드 간의 연결을 통해 순차 액세스도 효율적으로 수행할 수 있게 설계되어 있습니다.

예를 들어, user_id에 인덱스가 걸려 있는 users 테이블에서 특정 user_id를 가진 레코드를 조회하는 쿼리가 있다고 가정해봅시다.

SELECT * FROM users WHERE user_id = 123;

이 쿼리를 실행할 때, MySQL은 user_id 인덱스의 B+Tree 구조를 통해 user_id 값이 123인 레코드의 위치를 빠르게 찾아냅니다. 그리고 해당 위치에 직접 접근하여 데이터를 가져오게 됩니다. 이러한 직접 접근 방식이 랜덤 액세스입니다.

따라서, 인덱스를 사용하면 MySQL은 테이블 전체를 스캔하는 대신 랜덤 액세스를 통해 필요한 데이터만 빠르게 가져올 수 있어 성능이 효율적으로 향상됩니다.

4. 랜덤액세스의 종류

랜덤액세스에는 3가지 종류가 있습니다.
확인, 추출, 정렬

1. 확인 랜덤 액세스 (Confirmation Random Access):

이 방식은 특정 데이터나 조건의 존재 유무를 확인하는 것을 목적으로 합니다.
예를 들어, EXISTS나 IN, NOT IN과 같은 서브쿼리에서 주로 발생합니다.
예:

SELECT * FROM orders WHERE order_id IN (SELECT order_id FROM shipped_orders);

위 쿼리에서 shipped_orders 테이블의 order_id를 확인하는 과정에서 확인 랜덤 액세스가 발생할 수 있습니다.

2. 정렬 랜덤 액세스 (Sorting Random Access):

이 방식은 데이터를 특정 순서로 정렬하기 위해 사용됩니다.
인덱스를 활용하면, 이미 정렬된 상태로 데이터를 빠르게 액세스할 수 있습니다.
그러나 인덱스가 없거나 다른 조건으로 인해 인덱스를 활용하지 못할 경우, 데이터베이스는 추가적인 정렬 연산을 수행해야 하며, 이때 정렬 랜덤 액세스가 발생합니다.

예:

SELECT * FROM users ORDER BY user_name ASC;

만약 user_name에 인덱스가 있다면, 인덱스를 활용하여 정렬된 상태로 빠르게 데이터를 액세스합니다.

3. 추출 랜덤 액세스 (Retrieval Random Access):

이 방식은 특정 조건에 맞는 데이터를 실제로 추출하는 것을 목적으로 합니다.
인덱스를 활용하여 특정 조건에 맞는 데이터의 위치를 빠르게 찾아내고, 해당 위치에서 데이터를 직접 읽어옵니다.

예:

SELECT * FROM users WHERE age > 30;

만약 age 컬럼에 인덱스가 있다면, 30세 이상의 사용자 데이터의 위치를 빠르게 찾아내고, 해당 위치에서 데이터를 직접 액세스합니다.


Reference

  1. https://loosie.tistory.com/843
  2. https://sas-study.tistory.com/448
  3. http://www.gurubee.net/people/axiom
profile
내맘대로 주제잡고 재미로 글쓰는 개발일지 블로그 👨‍💻

0개의 댓글