MongoDB 와일드카드 인덱스
MongoDB 와일드카드 인덱스 (Wildcard Indexes)
도큐먼트마다 필드 이름이 제각각이라 어떤 필드를 조회할지 미리 알기 어려울 때 와일드카드 인덱스가 도움이 돼요. MongoDB는 유연한 스키마를 지원해서 같은 컬렉션 안에서도 도큐먼트의 필드 이름이 서로 달라질 수 있어요. 임의의 또는 아직 정해지지 않은 필드에 대한 쿼리를 지원하려면 와일드카드 인덱스를 사용합니다.
와일드카드 인덱스 만들기
와일드카드 인덱스는 인덱스 키에 $**라는 특별한 와일드카드 지정자를 넣어서 만들어요.
db.collection.createIndex( { "$**" : <sortOrder> } )
정렬 순서 자리에는 1 같은 값을 넣어요. 이렇게 하면 도큐먼트의 어떤 필드 이름으로 조회하든 그 쿼리를 지원할 수 있어요.
언제 쓰면 좋을까
와일드카드 인덱스는 대상 필드가 불명확하거나 자주 바뀔 때만 써야 해요. 특정 필드를 겨냥한 인덱스만큼 성능이 좋지 않기 때문이에요. 컬렉션에 필드 이름이 제각각이라 특정 필드 인덱스를 만들기 어려운 상황이라면, 차라리 스키마를 재설계해서 필드 이름을 일관되게 만드는 방안을 먼저 고려해 봐요.
와일드카드 인덱스가 특히 유용한 상황은 이래요.
- 도큐먼트마다 필드 이름이 달라서 모든 가능한 필드 이름의 쿼리를 지원하고 싶은 경우
- 임베디드 도큐먼트의 서브필드가 일정하지 않아 그 서브필드 전부를 조회해야 하는 경우
- 공통된 특징을 공유하는 도큐먼트를 조회하는 경우. 이때 복합 와일드카드 인덱스가 공통 필드를 가진 많은 쿼리를 효율적으로 커버할 수 있어요.
동작 방식과 주의점
- 컬렉션에 와일드카드 인덱스를 여러 개 만들 수 있어요.
- 와일드카드 인덱스는 컬렉션의 다른 인덱스와 같은 필드를 커버할 수도 있어요.
- 와일드카드 인덱스는 기본적으로
_id필드를 제외해요._id를 포함하려면wildcardProjection문서에{ "_id": 1 }을 명시해야 해요. - 와일드카드 인덱스는 희소 인덱스라서, 인덱스 필드를 가진 도큐먼트만 항목이 생겨요. 값이
null이어도 포함돼요. - 와일드카드 인덱스는 와일드카드 텍스트 인덱스와는 다르고 호환되지 않아요.
$text연산자를 사용하는 쿼리를 지원하지 못해요.
커버드 쿼리
와일드카드 인덱스는 다음 조건을 모두 만족할 때만 커버드 쿼리(covered query)를 지원해요.
- 쿼리 플래너가 와일드카드 인덱스를 선택한 경우
- 쿼리 조건이 와일드카드 인덱스가 커버하는 필드 하나만 정확히 지정한 경우
- 쿼리의 프로젝션이
_id를 명시적으로 제외하고 쿼리 필드만 포함한 경우 - 지정한 쿼리 필드가 배열이 아닌 경우
예를 들어 employees 컬렉션에 이런 와일드카드 인덱스가 있다고 해볼게요.
db.employees.createIndex( { "$**" : 1 } )
lastName 필드 하나만 조회하고 나머지 필드는 프로젝션으로 뺀 다음 쿼리에서 lastName이 배열이 아니라면,
db.employees.find( { "lastName" : "Doe" }, { "_id" : 0, "lastName" : 1 } )
MongoDB가 $** 와일드카드 인덱스로 이 쿼리를 커버드 쿼리로 처리할 수 있어요.