MongoDB 인덱스 - null 필드 처리
MongoDB 인덱스 - null 필드 처리
이 글은 2024년 11월 Velog에 작성했던 글 입니다
MongoDB는 NoSQL이기 때문에 필드 구조가 일정하지 않을 수 있다. 그렇다면 인서트한 도큐먼트에 인덱스를 건 필드가 존재하지 않는다면 어떻게 처리될까? 아래 네 가지 경우 각각 어떻게 처리되는지 궁금했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 1. 일반 인덱스
db.collection.createIndex({ "name": 1 })
// 2. 희소 인덱스
db.collection.createIndex({ "name": 1 }, { sparse: true })
// 3. 부분 인덱스
db.collection.createIndex({ "name": 1 },
{
partialFilterExpression: {
name: {$ne: null}
}
})
// 4. 유니크 인덱스
db.collection.createIndex({ "name": 1 }, {unique:true})
// 데이터 입력 예시
db.collection.insert({
"name": "다영",
"age": 11
})
// 이 상황!!! -> 여기서 어떻게 처리되지?
db.collection.insert({
"nickname": "dy",
"age": 13
})
1. 일반 인덱스
1
db.collection.createIndex({ "name": 1 });
특징
- 컬렉션의 모든 문서를 대상으로 인덱스를 생성
- name 필드가 없어도 해당 문서가 인덱스에 포함됨!! -> null로 간주되어 인덱스에 Null값으로 저장됨
빈 값 처리
- name 필드가 없는 문서가 있으면 null 값으로 인덱스에 저장되기 때문에, name이 존재하지 않는 문서까지도 인덱스 검색 결과에 포함된다
- db.collection.find({ “name”: null }) -> name 필드 없는 문서 인덱스로 조회
2. 희소 인덱스(sparse index)
1
db.collection.createIndex({ "name": 1 }, { sparse: true });
특징
- 필드가 존재하는 문서에 대해서만 인덱스를 생성
- name 필드가 없는 문서는 인덱스에 포함되지 않음
빈 값 처리
- name 필드가 없는 문서는 아예 인덱스에 포함X
- {name:null} 로 지정하여 데이터를 저장하면 인덱스에 포함하여 저장함!!
특이사항
1
2
3
4
5
6
7
8
9
10
11
12
db.collection.createIndex({ "name": 1 }, { sparse: true });
db.collection.insert({ // name필드 저장 x -> sparse인덱스에 포함되지 않음
"nickname": "dy",
"age": 13
})
db.collection.insert({ // name필드 null로 저장 -> sparse인덱스에 포함됨
"name": null,
"age": 13
})
db.collection.find({ "name": null })
위 경우에는 어떻게 인덱스를 타지??
- 일단 조회는 의도한대로 되는 것 확인됨
- 혹시몰라 데이터를 500건씩 넣고 검색해봤지만 COLLSCAN(풀스캔)을 하고 있는것을 확인
- 인덱스 문제는 아님(string 검색할때는 인덱스 잘 탐)
그렇다면 아예 Null인 데이터만 넣은 경우에는 인덱스를 타나?(필드 없는 경우 없이 모두 인덱스를 인서트한 경우)
- 안탄다…
결론
- sparse 인덱스는 필드가 비어있으면 해당 필드를 제외하고 인덱스를 저장한다
- 인덱스 필드를 null로 지정하면 해당 인덱스를 포함하여 저장한다
- 다만 null로 검색해도 인덱스를 사용하지는 않는다
3. 부분 인덱스(partial index)
1
2
3
4
5
6
db.collection.createIndex({ "name": 1 },
{
partialFilterExpression: {
name: {$ne: null}
}
});
- 특정 조건을 만족하는 문서에 대해서만 인덱스를 생성
- 위의 설정은 name 필드가 null이 아닌 문서만 인덱스에 포함하도록 지정
빈 값 처리
- name 필드가 null이거나 필드 자체가 존재하지 않는 문서는 인덱스에 포함되지 않움
- db.collection.find({ “name”: null }) -> 인덱스 사용 안됨
- 희소 인덱스(sparse index)와 차이점
- name:null 값을 null로 지정해서 저장해도 부분인덱스에는 저장되지 않는다
- 메모리 확보 면에서 부분 인덱스가 뛰어남
- 공식 문서에서도 sparse인덱스보다 부분인덱스를 활용하는것을 권장하고 있다
4. 유니크 인덱스(unique index)
1
db.collection.createIndex({ "name": 1 }, { unique: true });
- 인덱스 필드 값이 중복되지 않도록 강제함
- 기본적으로 MongoDB에서는 null 값도 유니크하게 취급합
- 따라서 name 필드가 없는 문서는 name이 null로 인식되며, 중복된 null 값이 허용되지 않음
빈 값 처리
정리
| 인덱스 종류 | name 필드가 없는 문서 인덱스 포함 여부 | name:null 문서 인덱스 포함 여부 | 중복 null 허용 여부 | 빈 값 처리 결과 | | :—- |:—- |:—- |:—- |:—- | |일반 인덱스 | 포함|포함| 허용 | null로 인덱싱됨 | |희소 인덱스 | 미포함|포함| 허용 | 인덱스 미포함 | | 부분 인덱스 | 미포함(조건에 따라 다름) |미포함(조건에 따라 다름) | 허용| 인덱스 미포함 | | 유니크 인덱스 | 포함(null로 취급) | 포함 | 미허용 | null 검색 시 인덱스 활용 |
This post is licensed under CC BY 4.0 by the author.