본문 바로가기
면접

데이터베이스 질문

by L3m0n S0ju 2023. 5. 17.

데이터베이스 인덱스란 무엇이며, 어떻게 작동하나요?

데이터베이스 인덱스(Index)는 테이블의 특정 열(Column)에 대한 검색 성능을 향상시키기 위해 사용되는 데이터 구조입니다. 즉, 인덱스는 테이블의 데이터를 더 빠르게 검색할 수 있도록 도와주는 기능입니다.

인덱스는 대개 B-트리(B-tree) 또는 해시(Hash) 구조를 사용하여 구현됩니다. B-트리 인덱스는 데이터베이스에서 가장 많이 사용되는 인덱스 구조 중 하나입니다.

인덱스를 사용하면 데이터베이스 검색 성능이 향상되지만, 인덱스는 추가적인 공간과 오버헤드를 발생시키므로 모든 열에 대해 인덱스를 생성하는 것은 권장되지 않습니다. 적절한 인덱스를 생성하면 데이터베이스의 검색 성능을 크게 향상시킬 수 있습니다. 예를 들어 게시글 제목을 검색할 때 게시글의 기본 값은 id이므로 제목에 대한 검색은 최적화 되어 있지 않습니다. 하지만 인덱스를 설정하면 인덱스는 게시글 제목을 알파벳 순서대로 정렬하여 저장하고 검색 시 데이터베이스 엔진은 이 인덱스를 검색하고, 검색 결과로 나온 인덱스의 주소를 사용하여 해당 레코드를 찾아갑니다. 이렇게 인덱스를 사용하면 검색 시 테이블 전체를 순차적으로 검색하는 것보다 검색 속도가 훨씬 빨라지게 됩니다.

 

 

 


b-tree와 해시 인덱스 차이점

B-tree 인덱스


범용성: B-tree는 범용적으로 사용될 수 있으며 여러 종류의 쿼리에서 효과적입니다. 범위 쿼리나 정렬된 결과를 필요로 하는 쿼리에 적합합니다. 해시는 특정 값에 대한 검색에 최적화되어 있어 범위 쿼리나 정렬된 결과를 필요로 하는 경우에는 B-tree보다 성능이 떨어질 수 있습니다.

순차적 접근: B-tree는 트리의 구조로 인해 순차적인 접근이 빠릅니다. 범위 쿼리에서 유리하게 동작합니다. 해시 인덱스는 데이터가 무질서하게 저장되므로 순차적인 접근이 느리고 정렬 기능이 없습니다. 하지면 개별 쿼리에서는 해시 함수가 직접 해시를 계산하여 검색을 하므로 상수의 시간 복잡도가 되기 때문에 매우 빠르다고 한다.


균형 트리: B-tree는 삽입과 삭제 작업에도 효율적으로 동작하도록 균형이 잘 맞춰진 구조를 유지합니다.

간단한 구조: B-tree는 복잡한 구조를 가지고 있기 때문에 구현이 상대적으로 복잡합니다. 해시 인덱스는 간단한 구조로 이루어져 있어서 구현이 비교적 간단합니다.



 

 


ACID란 무엇이며, 데이터베이스에서 왜 중요한가?

 

ACID는 데이터베이스 트랜잭션의 속성을 나타내는 약어로서 다음과 같이 정의됩니다:


- Atomicity (원자성): 트랜잭션은 일련의 작업 중 하나라도 실패하면 전체를 실패 처리해야 합니다. 즉, 트랜잭션은 전부 실행되거나 전혀 실행되지 않아야 합니다.
- Consistency (일관성): 트랜잭션이 실행되기 전과 실행된 후의 데이터 상태가 일관성이 있어야 합니다. 즉, 데이터는 미리 정의된 규칙을 준수해야 합니다.
- Isolation (독립성): 복수의 트랜잭션이 동시에 실행되더라도, 각각의 트랜잭션은 다른 트랜잭션에 영향을 미치지 않는 독립성을 보장해야 합니다.
- Durability (지속성): 트랜잭션이 성공적으로 완료된 후, 해당 결과는 영구적으로 저장되어야 합니다. 즉, 데이터베이스 시스템에 장애가 발생하더라도 데이터는 보존되어야 합니다.

 

 

ACID는 데이터베이스의 안정성과 일관성을 보장하기 위한 기본 원칙으로, 데이터의 신뢰성과 정확성을 유지하는 데 중요한 역할을 합니다. 예를 들어, 어떤 은행 애플리케이션이 사용자가 계좌 이체를 요청하는 경우, 해당 트랜잭션은 성공하거나 실패해야 합니다. 실패할 경우 이체가 취소되어야 하며, 이를 보장하기 위해서는 트랜잭션의 일관성과 원자성을 유지해야 합니다. 또한, 다중 사용자 환경에서 동시에 접근하는 경우에도 각각의 트랜잭션이 서로 영향을 미치지 않도록 독립성을 보장해야 합니다.

따라서 ACID는 데이터베이스의 신뢰성과 안정성을 보장하기 위한 핵심 개념으로, 대규모 시스템에서도 일관성 있는 데이터를 유지하고 안정적으로 운영할 수 있도록 도와줍니다.

 

 

 


 RDBMS와 NoSQL 데이터베이스의 장단점을 설명해보세요.

 

RDBMS (Relational Database Management System):

장점:

- 정형 데이터에 적합하며, 데이터의 일관성과 무결성을 보장합니다.
- 복잡한 관계를 가진 데이터를 효과적으로 다룰 수 있습니다.

 

단점:

- 수평 스케일링이 어려울 수 있습니다.
- 대량의 데이터 처리에는 느릴 수 있습니다.
- 스키마 변경이 번거롭고 유연성이 부족할 수 있습니다.

 

NoSQL (Not Only SQL) 데이터베이스:

장점:

- 다양한 형식과 비정형 데이터에 적합하며, 스키마 변경이 유연합니다.
- 수평 스케일링이 용이하며, 대규모 데이터 처리와 분산 환경에 적합합니다.

 

단점:

- 데이터 일관성과 트랜잭션 처리가 제한될 수 있습니다.
- 복잡한 관계를 다루기에는 부적합할 수 있습니다.

 

 

 


주어진 시나리오에서 대용량 데이터를 처리해야 할 때, 어떤 접근 방식을 고려하겠습니까?

 

수평확장이 쉬운 NoSQL을 DB로 사용하여 분산 시스템을 통해서 데이터 처리를 빠르게 할 수 있습니다.

 

대용량 데이터는 아마 다양한 형식의 데이터가 있을텐데 Restful API 대신 GraphQL을 사용해서 원하는 데이터만 효율적으로 가져올 수 있습니다.


- 데이터베이스 최적화:
데이터베이스 인덱스를 잘 설계하고, 쿼리 튜닝 및 데이터 정규화 등을 통해 데이터베이스 성능을 향상시킬 수 있습니다.

- 캐싱과 메모리 사용:
데이터 중에서 자주 접근되는 데이터를 캐싱하여 메모리에 보관하면 접근 속도를 높일 수 있습니다. 메모리 기반 데이터베이스나 인메모리 데이터 그리드를 사용하여 데이터를 빠르게 처리할 수 있습니다.

- 데이터의 중요도 파악:
모든 데이터가 동일한 중요도를 가지지 않을 수 있습니다. 중요한 데이터와 덜 중요한 데이터를 구분하여 처리 방식을 다르게 설정함으로써 리소스를 효율적으로 사용할 수 있습니다.

 

 


데이터베이스 최적화와 관련하여 어떤 경험이나 고민을 해보셨나요?

JPA에서 @Index 어노테이션으로 인덱스를 설정하는 정도만 해보았습니다. 하지만 데이터가 작아서 의미 있는 시간 감축을 없었습니다.

 

페치 조인을 통해서 n+1 문제를 해결한 경험이 있습니다. 게시글 컬럼 데이터를 가져올 때 lazy loading을 사용하기 때문에 작성자 수만큼 추가적인 쿼리가 날아가서 글을 가져오는데 6초 가량 걸렸었는데 절반 수준으로 시간 감축에 성공했습니다.

 

스프링에서 제공하는 캐싱 기능을 통해서 데이터를 가져오는데 6초 정도 걸리던 시간을 1초 이내로 줄였습니다.

 

 

 


MySQL과 PostgreSQL의 차이

 

MySQL이 조금 더 가볍고 성능이 좋지만 PostgreSQL이 더 많은 기능을 제공하고 확장성이 더 뛰어난 것으로 알고 있습니다.

 

 

 

 


Transaction 격리 수준

 

READ UNCOMMITTED (커밋되지 않은 읽기):

 

- 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있습니다. 

 

문제점: 데이터 불일치 문제가 발생할 수 있으며, 이 격리 수준은 트랜잭션의 격리 정도가 가장 낮은 수준입니다.

 

 

READ COMMITTED (커밋된 읽기):

 

- 트랜잭션이 커밋된 데이터만 읽을 수 있습니다.

- 다른 트랜잭션에서 변경 중인 데이터에 대한 읽기는 허용되지 않습니다.

 

문제점: 한 트랜잭션에서 같은 쿼리를 두 번 실행해도 다른 결과를 얻을 수 있습니다. 

 

 

REPEATABLE READ (반복 가능한 읽기):

  • 트랜잭션이 읽은 데이터는 다른 트랜잭션이 변경하더라도 동일한 값을 유지합니다. 예를 들어 a 데이터를 두 번 가져올 때 그 사이에 다른 사용자가 a를 변경하고 커밋하는 경우 두 번째 a를 조회할 때 값이 변경되었지만 다른 사용자가 a를 변경하는 시점은 첫 번째 a를 조회하는 시점 이후 이므로 언두 로그를 참고하여 a가 변경되기 이전의 데이터를 조회한다.
  • 따라서 한 트랜잭션 내에서 같은 쿼리를 여러 번 실행해도 항상 같은 결과를 얻을 수 있습니다.

문제점: Phantom Read -> 한 트랜잭션에서 쿼리가 여러개인 경우 중간에 다른 트랜잭션에서 데이터를 추가 및 삭제할 수 있음

 

 

SERIALIZABLE (직렬화 가능):

  • 가장 높은 격리 수준으로, 트랜잭션이 일어나는 동안 다른 트랜잭션이 해당 데이터에 접근할 수 없습니다.
  • 모든 읽기와 쓰기 작업은 트랜잭션 내에서 완료된 후에만 다른 트랜잭션에게 공개됩니다.

 

오라클에서는 READ COMMITTED를 기본으로 사용하며, MySQL에서는 REPEATABLE READ를 기본으로 사용한다. 

  Dirty Read Non-Repeatable Read Phantom Read
READ UNCOMMITED 발생 발생 발생
READ COMMITTED 없음 발생 발생
REPEATABLE READ 없음 없음 발생(MySQL은 거의 없음)
SERIALIZABLE 없음 없음 없음

 

 

'면접' 카테고리의 다른 글

스프링과 nestjs의 차이점  (0) 2023.07.01
정규 표현식  (0) 2023.06.30
Spring 질문  (0) 2023.05.17
DevOps 이것저것  (0) 2023.04.06
하는김에 프론트엔드 면접도...  (0) 2023.04.06

댓글