다음은 웹 개발자를 위한 대규모 서비스를 지탱하는 기술을 읽고 정리한 내용입니다 🙌


이번장은 레이어를 DB로 옮겨서 DB의 스케일아웃 전략에 대해서 살펴본다.

[강의11] 인덱스 올바르게 운용하기

분산을 고려한 MySQL 운용, 세 가지 포인트

  1. OS 캐시 활용
  2. 인덱스를 적절하게 설정
  3. 확장을 전제로 한 설계

OS 캐시 활용

전체 데이터 크기가 물리 메모리보다 가능한 적도록 유지한다.

  • 상황: 대규모 서비스일 경우 (3억건의 데이터), 테이블에 칼럼을 한 개 (약 8바이트)를 추가하더라도 3GB 가 추가된다. → 스키마도 신경써서 설계해야한다.
  • 따라서 테이블의 레코드를 컴팩트하게 설계해야한다. (int형 32비트, 문자열 8비트 같은 수치에 대한 감각 필요)

DB 테이블의 데이터를 정규화하는 것은 ?

  • 예를 들어서 필수적으로 필요한 데이터만 테이블에 남기고, flag로 사용되는 데이터들을 테이블 분리하여 필요할 때만 사용할 수도 있다. 대규모 데이터인 경우 이것만 분리를 하더라도 엄청난 용량이 줄어든다.
  • 하지만 쿼리가 복잡해져서 속도가 떨어질 수 있으므로 속도와 데이터 크기 간 트레이드 오프가 있다는 것도 생각해야한다. !!!

인덱스의 중요성 - B+트리

DB의 인덱스는 탐색이 매우 빠른 B+트리 구조를 사용한다.

이분탐색과 비교해서 더 디스크에 최적화 되어 있다 → 더 알아보아야겠지만 하나의 노드에 있는 내용들은 디스크 액세스를 하지 않아도 된다.

인덱스의 효과

4000만건의 테이블이 있을때를 고려해보면,

  • 만일 인덱스가 없다면 선형탐색을 함 → O(n) 최대 4000만번 탐색
  • 인덱스 있다면 → O(logn) 최대 25.5번

하지만 데이터가 작은 경우 트리를 순회하는 오버헤트가 더 클수도 있으므로 잘 판단하여 인덱스를 사용한다.

+ MySQL 특성에 따른 인덱스의 작용

특정 칼럼에 인덱스를 걸어놓더라도 사용하는 쿼리에 따라서 사용하지 않을수도 있다.

  • 기본적으로 where, order by, group by 조건문이 지정되는 칼럼에 인덱스를 사용한다.
  • 인덱스를 명시적으로 추가한 것 이외에 pk, unique 제약조건에 인덱스를 가지고 있다. (show index로 인덱스 내용 확인 가능)
  • 조건문에 여러 인덱스 칼럼이 사용되도, 하나의 인덱스만 사용된다. (따라서 여러 칼럼이 한꺼번에 조건으로 될 경우 복합 인덱스를 설정해야한다)
  • 인덱스 설정에 대해서는 더 알아보자 !!
  • explain 명령어로 인덱스 작용을 확인할 수 있다.

인덱스의 간과

  • 나도 모르게 인덱스가 작용하지 않은 쿼리를 사용하고 있을수도 있다.
    • 자동으로 쿼리를 생성해주는 툴을 사용하면서 이것을 간과하게 된다.
    • 감시방안을 늘려서 대응해야한다.

[강의12] MySQL의 분산

MySQL replication 기능

  • Master, slave 구조이며 slave가 master의 replica가 되는 것이다.
  • 갱신은 마스터에서만 이루어지며 slave는 조회 쿼리만 담당한다.

Master/Slave의 특징

  • select는 분산할 수 있지만 갱신은 분산할 수 없으므로 마스터의 다중화의 문제가 발생한다.
  • 하지만 대부분 쓰기보다 읽기가 훨씬 많으므로 읽기용 slave가 많은 것이 분산에 큰 효과를 낸다.

갱신 및 쓰기 확장

이런 경우에는 테이블을 분할해서 그 크기를 매우 작게 한다. 이것으로 쓰기 작업이 분산된다.

  • 테이블 파일이 분산 될 경우 동일 호스트 내에서 여러 디스크를 가지고 분산할 수 있고, 다른 서버로 분산할 수도 있다.
  • 쓰기 작업이 너무 많다면 RDBMS를 사용하지 않고 KVS 방식을 사용하는 것도 고려할 수 있다. (오버헤드가 적고 빠르며 확장이 쉽다)

[강의13] MySQL의 스케일아웃과 파티셔닝

MySQL의 스케일아웃 전략

  • 일단 데이터가 메모리에 올라가는 크기면 메모리에 올리고, 올라가지 않으면 메모리를 증설한다.
  • 그리고 인덱스를 걸자 !!
  • 하지만 만일 메모리 증설이 어렵다면 파티셔닝을 한다.

파티셔닝에 관한 보충 (테이블 분할)

  • 테이블A와 테이블B를 다른 서버에 놓아서 분산하는 것.
  • 국소성을 활용해서 분산할 수 있고 캐싱이 유효하기 때문에 효과적이다.

파티셔닝을 전제로 한 설계

  • 상황: 두 테이블 사이에 연관관계가 존재하여 join 쿼리를 던져야하는 경우 두 테이블을 분할 수는 없다.
  • 두 개의 테이블이 다른 서버로 분할되면 JOIN을 할 수 없지만 이것을 두 개의 쿼리로 나눠서 질의하면 가능하게 만들 수 있다. → 그러면 파티셔닝이 가능하게 된다.
    • 하지만 너무 밀접할 경우 같은 서버에 놓고 join을 하는 것이 더 효율적이다.

JOIN 배제 - where, in 활용

  • 위에 말한 경우이다. 먼저 어떤 테이블에 관련 Id를 질의하고 해당 id를 가지고 원하는 데이터를 뽑아내도록 한다. (JPA를 활용할 경우는 어떻게 하는 것이 좋을까)
  • 다수의 DB를 찔려서 하나의 쿼리에서 다수의 DB 서버 액세스 가능? (키워드 MSA)

파티셔닝의 상반관계 - 단점

  1. 운용이 복잡해진다. → 다른 용도의 서버가 생긴다.
  2. 고장률이 높아진다 → 대수가 늘어나므로 고장률 또한 증가한다.
  3. 어플리케이션 용도와 서버 대수
    1. 무정지가 되려면 여러개의 서버대수가 필요하고 해당 서버를 분할하면 기하급수적으로 많아진다.

파티셔닝은 언제나 마지막 카드이다 !!!