[MongoDB 인덱스]
-
컬렉션 당 최대 64개의 인덱스만 생성 가능
-
너무 많은 인덱스를 추가하면 오히려 부작용 발생
-
모든 인덱스를 메모리에 보관하기 때문에 인덱스가 많아지면 Frequent Swap 발생
-
그러면 Write Performance 감소함
-
인덱스가 너무 많으면 쿼리 플래너가 잘못된 인덱스를 선택할 가능성도 높아짐
[인덱스 prefix]
-
여러 개의 항목에 대해 인덱스를 설정할 수 있음
-
한 인덱스에 a, b, c 항목을 순서대로 정의하고 나중에 쿼리를 보낼 때, (a), (a,b), (a,b,c)를 조건으로 전달할 수 있음
-
그러나, (b), (c), (b,c), (a,c)는 조건으로 전달해도 인덱스가 사용되지 않음
-
단, (a,c)를 전달하면 a에대한 인덱스만 사용됨
[멀티소팅]
-
정렬 키들은 반드시 인덱스와 같은 순서로 나열되어야만 한다.
-
싱글 필드면 소팅 방향을 걱정할 필요 없음. 그러나, 복합 인덱스는 소팅 방향이 중요함
-
a:1, b:1로 복합 인덱스 설정시, (a:1, b:1), (a:-1, b:-1), (a:1), (a:-1)은 지원이 됨
[성능 높이기]
#컬렉션 나누기
-
하나의 컬렉션을 여러 개의 컬렉션으로 나누기
-
카디널리티를 높이기 위해 컬렉션을 나누는게 좋다. (예: 성별, 연령 등)
-
카디널리티가 너무 낮은 항목에 대해 인덱스를 설정할 수 밖에 없는 상황이라면 별도의 컬렉션으로 빼는게 낫다.
#스레드를 이용해 대량의 다큐먼트 upsert
-
한번 배치가 돌 때 upsert 치는 양이 8000개에서 만개정도 됨
-
여러 개의 스레드에서 bulk operation으로 많은 다큐먼트를 한번에 write
#MongoDB 4.0
-
이전에는 non-blocking secondary read 기능이 없었음
-
[기존] write가 primary에 반영되고 secondary들에 다 전달될 때 까지 secondary는 read를 block해서 데이터가 잘못된 순서로 read 되는 것을 방지함
-
[기존] 그래서 주기적으로 높은 global lock acquire count가 생기가 read 성능이 저하됨
-
[현재] data timestamp와 consistent snapshot을 이용해서 이 이슈를 해결함
-
non-blocking secondary read
[미운 인덱스]
-
공연 컬렉션의 문서 수 : 9만건
"오늘 공연"
db.concert.count({serviceCode:{$in:[2,3]},startDate:{$lte:20190722},endDate:{$gte:20190722});
>>> 270ms
"서울 공연"
db.concert.count({serviceCode:{$in:[2,3]},region:"se",isNow:1});
>>> 290ms
#explain 결과
-
"오늘 공연"
-
{serviceCode:1,weight:1} 인덱스를 사용 (key examined: 88226) >> 거의 다 읽음
-
"서울 공연"
-
{region:1,weight:1} 인덱스를 사용 (key examined: 25322)
-
key examined의 값을 줄여야 함
#분석
-
"오늘 공연"
-
오늘 공연의 결과 값은 123개였음. 123개를 위해 8만개의 문서를 탐색함
-
startDate, endDate부터 실행하고 serviceCode부터 뒤지면 123개만 탐색하면 가능함
-
그러나 인덱스를 타지 않음
-
"서울 공연"
-
region이 "se"인 2만 5천개의 인덱스를 훑어보면서 메모리에서 isNow가 1이고 serviceCode가 2,3인 문서를 탐색함
-
isNow부터 검색하고 region, serviceCode를 검색하면 200여개만 탐색하면 됨
-
그러나 인덱스를 타지 않음
#인덱스를 타지 않는 이유
-
문제는 쿼리 플래너에 있었음
-
이전에 실행한 쿼리 플랜을 캐싱해 놓음
-
이전에 실행된 쿼리 플랜을 캐싱 해놓음. 캐싱된 쿼리 플랜이 없다면 가능한 모든 쿼리 플랜들을 조회해서 첫 batch (101개)를 가장 좋은 성능으로 가져오는 플랜을 다시 캐싱함
-
만약 동점이 나올 경우, in-memory sort를 하지 않아도 되는 쿼리 플랜을 선택함
-
몽고DB는 32MB가 넘는 결과 값들에 대해서는 in-memory sort가 불가능
[쿼리 실행 방법]
-
Hint 이용
-
확실한 쿼리플랜 보장
-
더 효율적인 인덱스가 생겨도 강제 고정
-
데이터 분포에 대한 정보를 계속 follow 해야 함
-
32MB가 넘는 응답결과를 sort해야할 경우 에러
-
엄한 인덱스 지우기
-
데이터에 따라 더 효율적인 인덱스가 생기면 자동 대응
-
또 다른 엄한 케이스가 생길 수 있음
-
삭제로 인해 영향을 받는 다른 쿼리가 생길 수 있음
'컴퓨터 공학' 카테고리의 다른 글
코드 이름 표기법 종류 (0) | 2022.01.12 |
---|---|
C++ vs Node.js vs Go - 멀티스레드 퀵정렬 수행속도 비교 (1) | 2021.06.07 |
AES 암호화 알고리즘 조사 (0) | 2021.04.17 |
2019년 국가 별 개발자 연봉 (0) | 2021.03.19 |
현재 시간을 filetime, unixtime, 포맷 형식으로 출력하는 프로그램 (0) | 2021.02.23 |