몽고디비 인덱스 정리 - 1
인덱싱 소개
인덱스를 사용하지 않은 쿼리를 컬렉션 스캔이라고 한다. 인덱스를 선택할때는 자주 사용되는 열을 적용하는것이 효과적이다. 예를들어, 자주 중복되지 않은 ID나 이메일 컬럼에 인덱스를 설정하면 좋다.
인덱스 생성
인덱스가 생성된 후에 아래와 같이 쿼리해보면 executionTimeMillis 가 1s로 쿼리 시간을 단축시켜준다. 하지만, 인덱싱은 필드를 변경하는 쓰기 작업은 오래 걸린다. 데이터가 변경될때 도큐먼트만 아니라 모든 인덱스를 갱신해줘야 하기 때문이다. (인덱스는 필드의 순서값을 유지하기 때문이다.)
복잡한 인덱스 소개
아래 쿼리는 email 로 정렬한 후에 name으로 정렬한다. 우리가 미리 만들어둔 name으로 정렬하는건 크게 도움이 되지 않는다. 정렬을 최적화하기 위해서는 email, name을 같이 복합 인덱스로 만들어야 한다.
그래서 복합 인덱스를 만들려면 아래와 같이 둔다. 내부적으로 보면 각 인덱스 항목은 email과 name 을 포함하고 있는 레코드 식별자를 만든다고 한다. 레코드 식별자는 내부에서 스토리지 엔진에 의해 도큐먼트 데이터를 찾는다.
아래와 같이 find 쿼리를 사용한다고 할때 몽고 디비는 이미 정렬된 email 과 일치하는 항목부터 순서대로 인덱스를 탐색하게 된다.
하지만, 다중값 쿼리를 할때 결과가 32메가바이트 이상이면 몽고DB는 데이터가 더누 많아 정렬을 거부한다는 요청을 보낸다. 복합 인덱스를 구성할 때는 정렬 키를 첫번째로 놓고 사용하면 좋다.
몽고DB가 인덱스를 선택하는 방법
여러 쿼리 플랜이 경쟁한다. 모양이 동일한 후속 쿼리가 있을 때는 몽고DB 서버에서 어떤 인덱스를 선택할 지 알 수 있다. 서버는 쿼리 플랜의 캐시를 유지하기 때문이다. 하지만, mongod 프로세스를 다시 시작할 때 삭제도니다.
복합 인덱스 사용
먼저 복합인덱스를 고려할때 트레이드오프가 필요할 수 있는 정렬이 처리되는 방식을 생각해보자. 테스트셋이 많지 않지만 두 인덱스를 생성했다고 가정해보자.
db.users.createIndex({"name" : 1})
db.users.createIndex({"name" : 1, "email" : 1})
email로 오른차순 정렬하고 name 과 email이 일치하는 데이터를 찾게된다. explain 을 통해서 실행통계를 살펴볼 수 있다. 여기서 몽고DB가 쿼리를 처리하는 방법에 대해 고민해볼 수 있다.
executionStats 필드는 쿼리 플랜에 대해 완료된 쿼리 실행을 설명한다. totalKeysExamined 이 필드는 몽고 DB가 결과 셋을 생성하기 위해 인덱스 내에 몇 개의 키를 통과했는지 나타낸다. 데이터셋이 많지 않아서 일치하는 도큐먼트 1개를 찾기 위해 인덱스 키 1개를 검사했다.
executionTimeMills 는 쿼리가 실행하는데 걸린 시간이다. 거의 뭐 0에 수렴한 값이 나왔다.
쿼리 플랜은 winningPlan 이 필드를 참조해보면 된다. rejeected 플랜은 안보인다. keyPattern 을 보면 email 키만 가지고 쿼리를 한것을 확인해볼 수 있다.
쿼리 시 hint 를 사용하면 사용할 인덱스를 지정할 수 있다. 쿼리 옵티마이저가 인덱스 필터에 지정된 인덱스만 고려하도록 제한 할 수 있다.
범위가 있는게 아니여서 유의미한 차이는 없는거 같다. totalKeysExamined, executionTimeMills 이 크게 차이나지 않아보인다.
find 시 id와 같은 숫자 범위를 입력하고 데이터셋을 늘리면 유의미한 데이터를 확인해볼 수 있을거 같다. hint 를 명시적으로 주면 좀 더 나은 인덱스 설계를 할 수 있다.
또 다른 경우는 복합 인덱스를 순서를 바꿔서 설계하여 explan 으로 쿼리 성능을 체크해보는 것이다. 인덱스를 잘 설계해야 인메모리 정렬을 피할 수 있다.
인덱스 생성 시 정렬에 필요한 인덱스는 앞에 두고 다중값 필터가 있는건 뒤에 둔다.
지금까지 이 챕터에서 나온 내용을 요약하면
- 동등 필터에 대한 키를 맨 앞에 표시한다.
- 정렬에 사용되는 키는 다중값 필드 앞에 표시되어야 한다.
- 다중값 필터에 대한 키는 마지막에 표시되어야 한다.
예)
//인덱스 생성
db.users.createIndex({ age: 1, category: 1 })
//쿼리
db.users.find({ category: { $in: ["A", "B"] } }).sort({ age: 1 })
ref
- 몽고 DB 완벽 가이드
//보완해야할 부분 : 데이터셋이 너무 약해서 복합 인덱스 구성 시 범위 쿼리나 힌트로 지정하여 인덱스 순서가 달라졌을 때 성능이 달리 보이지 않았음 -> 이 부분 데이터 셋 채우고 보완
'DataBase' 카테고리의 다른 글
Mongo : Transaction (0) | 2024.03.24 |
---|---|
Database01 :: TOPIC01 (0) | 2018.12.31 |
댓글
이 글 공유하기
다른 글
-
Mongo : Transaction
Mongo : Transaction
2024.03.24 -
Database01 :: TOPIC01
Database01 :: TOPIC01
2018.12.31