Indexes
이 페이지의 내용
개요
이 가이드에서는 MongoDB Java 드라이버로 인덱스를 사용하는 방법에 대해 설명합니다.
인덱스는 MongoDB에서 쿼리를 효율적으로 실행할 수 있도록 지원합니다. 인덱스가 없으면 MongoDB는 각 쿼리와 일치하는 문서를 찾기 위해 컬렉션의 모든 문서를 스캔(컬렉션 스캔)해야 합니다. 이러한 컬렉션 스캔은 속도가 느리고 애플리케이션 성능에 부정적인 영향을 미칠 수 있습니다. 쿼리에 적합한 인덱스가 있는 경우 MongoDB는 이 인덱스를 사용하여 검사해야 하는 문서를 제한할 수 있습니다.
인덱스는 다음과 같은 역할도 합니다.
팁
인덱스는 업데이트할 문서를 찾을 때 업데이트 작업, 삭제할 문서를 찾을 때 삭제 작업, 그리고 집계 파이프라인의 특정 단계에서도 사용됩니다.
쿼리 커버리지 및 성능
MongoDB에 대해 쿼리를 실행할 때 명령에 다양한 요소가 포함될 수 있습니다.
찾고 있는 필드와 값을 지정하는 쿼리 기준
쿼리 실행에 영향을 주는 옵션(예: 읽기 고려)
MongoDB가 반환하는 필드를 지정하기 위한 프로젝션 기준(선택 사항)
MongoDB에서 반환되는 문서의 순서를 지정하는 정렬 기준(선택 사항)
쿼리, 프로젝션, 정렬에 지정된 모든 필드가 동일한 인덱스에 있는 경우 MongoDB는 인덱스에서 직접 결과를 반환하며, 이를 커버 쿼리라고도 합니다.
중요
정렬 순서
정렬 기준은 인덱스의 순서와 일치하거나 반대가 되어야 합니다.
name
필드의 인덱스를 오름차순 (A-Z) 으로 age
인덱스를 내림차순 (9-0) 으로 가정해 보겠습니다.
name_1_age_-1
MongoDB는 다음 중 하나를 기준으로 데이터를 정렬할 때 이 인덱스를 사용합니다.
name
오름차순,age
내림차순name
내림차순,age
오름차순
name
및 age에 오름차순 정렬을 지정하거나 name 및 age
에 내림차순 정렬을 지정하려면 인메모리 정렬을 수행해야 합니다.
인덱스가 쿼리 기준 및 프로젝션을 커버하도록 하는 방법에 대한 자세한 내용은 쿼리 커버리지에 대한 MongoDB 매뉴얼 문서를 참조하세요.
운영 고려 사항
쿼리 성능을 향상시키려면 애플리케이션의 쿼리와 정렬된 결과를 반환하는 작업에 자주 나타나는 필드에 인덱스를 작성합니다. 추가하는 각 인덱스가 활성화되면 디스크 공간과 메모리를 사용하므로 용량 계획을 위해 인덱스 메모리와 디스크 사용량을 추적해야 합니다. 또한 쓰기 작업이 인덱스된 필드를 업데이트할 때는 MongoDB가 관련 인덱스도 업데이트해야 합니다.
MongoDB는 동적 스키마를 지원하므로 애플리케이션은 이름을 미리 알 수 없거나 임의적인 필드를 쿼리할 수 있습니다. MongoDB 4.2는 이러한 쿼리를 지원하기 위해 와일드카드 인덱스를 도입했습니다. 와일드카드 인덱스는 워크로드 기반 인덱스 계획을 대체하도록 설계되지 않았습니다.
데이터 모델을 설계하고 애플리케이션에 적합한 인덱스를 선택하는 방법에 대한 자세한 내용은 MongoDB Server 데이터 모델링 및 인덱스를 참조하세요.
인덱스 유형
MongoDB는 데이터 쿼리를 지원하기 위해 여러 가지 인덱스 유형을 지원합니다. 다음 섹션에서는 가장 일반적인 인덱스 유형을 설명하고 각 인덱스 유형을 생성하기 위한 샘플 코드를 제공합니다. 인덱스 유형의 전체 목록은 인덱스를 참조하세요.
다음 예에서는 createIndex() 메서드를 사용하여 다양한 인덱스를 만들고 다음과 같이 설정합니다.
import com.mongodb.DuplicateKeyException; import com.mongodb.MongoCommandException; import com.mongodb.client.*; import com.mongodb.client.model.IndexOptions; import com.mongodb.client.model.Indexes; import com.mongodb.client.model.Sorts; import com.mongodb.client.model.geojson.Point; import com.mongodb.client.model.geojson.Position; import org.apache.log4j.BasicConfigurator; import org.bson.Document; import org.bson.conversions.Bson; import static com.mongodb.client.model.Filters.*; import static com.mongodb.client.model.Projections.*;
final String uri = "mongodb+srv://<atlas-uri>/<dbname>?retryWrites=true&w=majority"; mongoClient = MongoClients.create(uri); database = mongoClient.getDatabase("sample_mflix"); collection = database.getCollection("movies");
단일 필드 및 복합 인덱스
단일 필드 인덱스
단일 필드 인덱스는 컬렉션 문서 내의 단일 필드에 대한 참조가 있는 인덱스입니다. 단일 필드 쿼리 및 정렬 성능을 향상시키고, 특정 시간 후 또는 특정 클록 시간에 컬렉션에서 문서를 자동으로 제거하는 TTL 인덱스 를 지원합니다.
참고
_id_
인덱스는 단일 필드 인덱스의 예입니다. 이 인덱스는 새 컬렉션이 생성될 때 _id
필드에 자동으로 생성됩니다.
다은 title
필드에 오름차순으로 인덱스를 생성하는 예입니다.
String resultCreateIndex = collection.createIndex(Indexes.ascending("title")); System.out.println(String.format("Index created: %s", resultCreateIndex));
다음은 앞에 설명한 코드 스니펫에서 생성된 인덱스로 처리되는 쿼리의 예입니다.
Bson filter = eq("title", "Batman"); Bson sort = Sorts.ascending("title"); Bson projection = fields(include("title"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
자세한 내용은 MongoDB 매뉴얼에서 단일 필드 인덱스를 참조하세요.
복합 인덱스
복합 인덱스에는 컬렉션의 문서 내에 있는 여러 필드에 대한 참조가 포함되어 있어 쿼리 및 정렬 성능을 향상시킵니다.
팁
복합 인덱스, 인덱스 접두사 및 정렬 순서에 대한 자세한 내용은 여기를 참조하세요.
다음 예에서는 type
및 rated
필드에 복합 인덱스를 만듭니다.
String resultCreateIndex = collection.createIndex(Indexes.ascending("type", "rated")); System.out.println(String.format("Index created: %s", resultCreateIndex));
다음은 앞에 설명한 코드 스니펫에서 생성된 인덱스로 처리되는 쿼리의 예입니다.
Bson filter = and(eq("type", "movie"), eq("rated", "G")); Bson sort = Sorts.ascending("type", "rated"); Bson projection = fields(include("type", "rated"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
자세한 내용은 MongoDB 서버 매뉴얼에서 복합 인덱스를 참조하세요.
다중 키 인덱스(배열 필드의 인덱스)
멀티키 인덱스는 배열 값을 포함하는 인덱스로 필드를 지정하는 쿼리의 성능을 개선하는 인덱스입니다. 단일 필드 또는 복합 인덱스와 동일한 구문을 사용하여 멀티키 인덱스를 정의할 수 있습니다.
다음 예시에서는 rated
, genres
(문자열 배열) 및 title
필드에 복합 멀티 키 인덱스를 생성합니다.
String resultCreateIndex = collection.createIndex(Indexes.ascending("rated", "genres", "title")); System.out.println(String.format("Index created: %s", resultCreateIndex));
다음은 앞에 설명한 코드 스니펫에서 생성된 인덱스로 처리되는 쿼리의 예입니다.
Bson filter = and(eq("genres", "Animation"), eq("rated", "G")); Bson sort = Sorts.ascending("title"); Bson projection = fields(include("title", "rated"), excludeId()); FindIterable<Document> cursor = collection.find(filter).sort(sort).projection(projection);
멀티키 인덱스는 쿼리는 쿼리 커버리지, 인덱스 바운드 계산, 정렬 행동 등에서 다른 인덱스와 다르게 작동합니다. 멀티키 인덱스의 동작과 한계에 대한 논의를 포함하여 멀티키 인덱스에 대해 자세히 알아보려면 MongoDB 매뉴얼의 Multikey Indexes(멀티키 인덱스) 페이지를 참조하세요.
Atlas Search 및 Vector Search 인덱스
Java 운전자 를 사용하여 Atlas Search 및 Atlas Vector Search 인덱스를 프로그래밍 방식으로 관리 수 있습니다.
Atlas Search 기능을 사용하면 MongoDB Atlas에서 호스팅되는 컬렉션에서 전체 텍스트 검색을 수행할 수 있습니다. MongoDB Atlas Search에 대해 자세히 학습하려면 Atlas Search Indexes 문서를 참조합니다.
Atlas Vector Search 를 사용하면 MongoDB Atlas 에 저장된 벡터 임베딩에 대해 시맨틱 검색을 수행할 수 있습니다. Atlas Vector Search 에 학습 보려면 애그리게이션 빌더 가이드 의 Atlas Vector Search 섹션을 참조하세요.
컬렉션 에서 다음 메서드를 호출하여 Atlas Search 및 Vector Search 인덱스를 관리 있습니다.
createSearchIndex()
( Atlas Search 인덱스에만 유효)createSearchIndexes()
listSearchIndexes()
updateSearchIndex()
dropSearchIndex()
참고
Atlas 검색 인덱스 관리 방법은 비동기적으로 실행됩니다. 드라이버 메서드는 성공적으로 실행되었는지 확인하기 전에 반환될 수 있습니다. 인덱스의 현재 상태를 확인하려면 listSearchIndexes()
메서드를 호출합니다.
다음 섹션에서는 코드 예시를 제공하여 이전의 각 메서드를 사용하는 방법을 보여줍니다.
검색 인덱스 만들기
createSearchIndex() 메서드를 사용하여 Atlas Search 인덱스 를 만들 수 있습니다. 이 메서드로는 Vector Search 인덱스 를 만들 수 없습니다.
다음 코드 예시에서는 Atlas Search 인덱스를 생성하는 방법을 보여줍니다.
Document searchIdx = new Document("mappings", new Document("dynamic", true)); collection.createSearchIndex("myIndex", searchIdx);
createSearchIndexes() 메서드를 사용하여 여러 개의 Atlas Search 인덱스 또는 하나 이상의 Vector Search 인덱스를 만들 수 있습니다. 각 인덱스 에 대해 SearchIndexModel 인스턴스 를 만들어 전달해야 합니다.
다음 코드 예시 에서는 한 번의 호출로 검색 및 벡터 검색 인덱스를 생성하는 방법을 보여줍니다.
SearchIndexModel searchIdxMdl = new SearchIndexModel( "searchIdx", new Document("analyzer", "lucene.standard").append( "mappings", new Document("dynamic", true)), SearchIndexType.search() ); SearchIndexModel vectorSearchIdxMdl = new SearchIndexModel( "vsIdx", new Document( "fields", Arrays.asList( new Document("type", "vector") .append("path", "embeddings") .append("numDimensions", 1536) .append("similarity", "dotProduct") ) ), SearchIndexType.vectorSearch() ); collection.createSearchIndexes( Arrays.asList(searchIdxMdl, vectorSearchIdxMdl) );
검색 인덱스 나열
listSearchIndexes() 메서드를 사용하여 컬렉션의 Atlas Search 인덱스를 반환할 수 있습니다.
다음 코드 예시에서는 컬렉션의 검색 인덱스 목록을 출력하는 방법을 보여줍니다.
try (MongoCursor<Document> resultsCursor = collection.listSearchIndexes().iterator()) { while (resultsCursor.hasNext()) { System.out.println(resultsCursor.next()); } }
검색 인덱스 업데이트
updateSearchIndex() 메서드를 사용하여 Atlas Search 인덱스를 업데이트할 수 있습니다.
다음 코드에서는 검색 업인덱스를데이트하는 방법을 보여줍니다.
collection.updateSearchIndex("myIndex", new Document("analyzer", "lucene.simple").append( "mappings", new Document("dynamic", false) .append("fields", new Document("title", new Document("type", "string"))) ) );
검색 인덱스 제거
dropSearchIndex() 메서드를 사용하여 Atlas Search 인덱스를 제거할 수 있습니다.
다음 코드에서는 컬렉션에서 검색 인덱스를 삭제하는 방법을 보여줍니다.
collection.dropSearchIndex("myIndex");
Text Indexes
텍스트 인덱스 는 문자열 콘텐츠에 대한 텍스트 검색 쿼리를 지원합니다. 이러한 인덱스에는 값이 문자열 혹은 문자열 요소의 배열인 필드가 있을 수 있습니다. MongoDB는 다양한 언어에 대해 텍스트 검색을 지원합니다. 인덱스를 생성하는 경우 기본값 언어를 옵션으로 지정할 수 있습니다.
팁
MongoDB 는 향상된 전체 텍스트 검색 솔루션인 Atlas Search 를 제공합니다. Atlas Search 인덱스 및 사용 방법에 학습 보려면 이 가이드 의 Atlas Search 및 Vector Search 인덱스 섹션을 참조하세요.
단일 필드
다음 예시에서는 plot
필드에 텍스트 인덱스를 생성합니다.
try { String resultCreateIndex = collection.createIndex(Indexes.text("plot")); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if a text index already exists with a different configuration } catch (MongoCommandException e) { if (e.getErrorCodeName().equals("IndexOptionsConflict")) System.out.println("there's an existing text index with different options"); }
다음은 앞의 코드 스니펫에서 생성된 인덱스를 사용하는 쿼리의 예입니다. 텍스트 인덱스에는 정렬 순서가 포함되어 있지 않으므로 sort
가 생략되었습니다.
Bson filter = text("java coffee shop"); Bson projection = fields(include("fullplot"), excludeId()); FindIterable<Document> cursor = collection.find(filter).projection(projection);
여러 필드
컬렉션에는 텍스트 인덱스 하나만 포함할 수 있습니다. 여러 텍스트 필드에 대해 텍스트 인덱스를 생성하려면 복합 인덱스를 생성해야 합니다. 텍스트 검색은 복합 인덱스 내의 텍스트 필드 모두에서 실행됩니다.
다음과 같은 스니펫은 title
및 genre
필드에 대한 복합 텍스트 인덱스를 생성합니다.
collection.createIndex(Indexes.compoundIndex(Indexes.text("title"), Indexes.text("genre")));
자세한 내용은 Server Manual Entries를 참조합니다.
지리 공간적 인덱스
MongoDB는 2dsphere 인덱스를 사용하여 지리 공간적 좌표 데이터 쿼리를 지원합니다. 2dsphere
인덱스를 사용하면 지리 공간적 데이터에 포함, 교차 및 근접성 등을 쿼리할 수 있습니다. 지리공간 데이터 쿼리에 대한 자세한 내용은 지리공간 쿼리를 참조하세요.
2dsphere
인덱스를 생성하려면 GeoJSON 객체만 포함하는 필드를 지정해야 합니다. 이 유형에 대한 자세한 내용은 GeoJSON 객체에 대한 MongoDB Server 매뉴얼 페이지를 참조하세요.
sample_mflix
데이터베이스의 theaters
컬렉션에 있는 다음과 같은 샘플 문서의 location.geo
필드는 시어터의 좌표를 설명하는 GeoJSON Point 객체입니다.
{ "_id" : ObjectId("59a47286cfa9a3a73e51e75c"), "theaterId" : 104, "location" : { "address" : { "street1" : "5000 W 147th St", "city" : "Hawthorne", "state" : "CA", "zipcode" : "90250" }, "geo" : { "type" : "Point", "coordinates" : [ -118.36559, 33.897167 ] } } }
다음 예시에서는 location.geo
필드에 2dsphere
인덱스를 생성합니다.
중요
지리 공간 인덱스에 포함된 필드에 지리 공간 인덱스를 생성하려고 하면 오류가 발생합니다.
try { String resultCreateIndex = collection.createIndex(Indexes.geo2dsphere("location.geo")); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if a geospatial index already exists with a different configuration } catch (MongoCommandException e) { if (e.getErrorCodeName().equals("IndexOptionsConflict")) System.out.println("there's an existing geospatial index with different options"); }
다음은 "location.geo" 인덱스를 사용하는 지리적 공간 쿼리의 예입니다.
// Stores the coordinates of the NY MongoDB headquarters Point refPoint = new Point(new Position(-73.98456, 40.7612)); // Retrieves documents that represent locations up to 1000 meters from the specified point directly from the geospatial index // Creates a filter to match a document Bson filter = near("location.geo", refPoint, 1000.0, 0.0); FindIterable<Document> cursor = collection.find(filter);
또한 MongoDB는 유클리드 평면에서 거리를 계산하고 MongoDB 2.2이하에서 사용되는 '레거시 좌표 쌍' 구문으로 작업하기 위한 2d
인덱스를 지원합니다. 자세한 내용은 MongoDB Server 매뉴얼의 Geospatial Queries(지리 공간적 쿼리) 페이지를 참조하세요.
Unique Indexes
고유 인덱스는 인덱스된 필드에 중복 값이 저장되는지 않도록 합니다. 디폴트로 MongoDB는 컬렉션 생성 시 _id
필드에 고유 인덱스를 생성합니다. 고유 인덱스를 생성하려면 중복을 방지하려는 필드 혹은 필드 조합을 지정하고 unique
옵션을 true
로 설정합니다.
다음 예시에서는 theaterId
필드에 고유한 내림차순 인덱스를 생성합니다.
try { IndexOptions indexOptions = new IndexOptions().unique(true); String resultCreateIndex = collection.createIndex(Indexes.descending("theaterId"), indexOptions); System.out.println(String.format("Index created: %s", resultCreateIndex)); // Prints a message if the "theaterID" field contains duplicate values } catch (DuplicateKeyException e) { System.out.printf("duplicate field values encountered, couldn't create index: \t%s\n", e); }
중요
고유 인덱스를 위반하는 중복 값을 저장하는 쓰기 작업을 수행하면 MongoDB Java 드라이버에서 DuplicateKeyException
오류가 발생하고 MongoDB에서 다음과 비슷한 오류가 발생합니다.
E11000 duplicate key error index
자세한 내용은 MongoDB Server 매뉴얼의 고유 인덱스 페이지를 참조하세요.
와일드카드 인덱스
와일드카드 인덱스를 활성화하면 알 수 없거나 임의의 필드에 대한 쿼리가 가능합니다. 이러한 인덱스는 동적 스키마를 사용하는 경우 유용할 수 있습니다.
다음 예에서는 하위 문서 및 배열에 중첩된 값을 포함하여 location
필드의 모든 값에 대해 오름차순 와일드카드 인덱스를 만듭니다.
String resultCreateIndex = collection.createIndex(Indexes.ascending("location.$**")); System.out.println(String.format("Index created: %s", resultCreateIndex));
자세한 내용은 MongoDB Server 매뉴얼의 와일드카드 인덱스 페이지를 참조하세요.
클러스터화된 인덱스
Clustered indexes는 키 값을 기준으로 정렬된 문서를 저장하도록 컬렉션에 지시합니다. 클러스터형 인덱스를 생성하려면 컬렉션을 생성하는 경우 _id
필드를 키로 사용하고 고유 필드를 true
로 사용하여 클러스터형 인덱스 옵션을 지정합니다.
다음 예시에서는 vendors
collection의 _id
필드에 클러스터형 인덱스를 생성합니다.
MongoDatabase database = mongoClient.getDatabase("tea"); ClusteredIndexOptions clusteredIndexOptions = new ClusteredIndexOptions(new Document("_id", 1), true); CreateCollectionOptions createCollectionOptions = new CreateCollectionOptions().clusteredIndexOptions(clusteredIndexOptions); database.createCollection("vendors", createCollectionOptions);
자세한 내용은 MongoDB Server 매뉴얼 섹션을 참조하세요.
인덱스 제거
_id
필드에서 기본값 고유 인덱스를 제외한 사용하지 않는 인덱스를 제거할 수 있습니다.
다음 섹션에서는 인덱스를 제거하는 방법에 대해 설명합니다.
인덱스 사양 문서 사용하기
인덱싱된 이름 필드 사용하기
와일드카드 문자를 사용하여 인덱스 모두 제거하기
인덱스 사양 문서를 사용하여 인덱스 제거
인덱스 사양 문서를 dropIndex()
메서드에 전달하여 컬렉션에서 인덱스를 제거합니다. 인덱스 사양 문서란 지정된 필드의 색인 유형을 지정하는 Bson
인스턴스를 말합니다.
다음 스니펫에서는 컬렉션의 title
필드에서 오름차순 인덱스를 제거합니다.
collection.dropIndex(Indexes.ascending("title"));
중요
텍스트 인덱스를 삭제하려면 그 대신 인덱스 이름을 사용해야 합니다. 자세한 내용은 Remove an Index Using a Name Field 섹션을 참조합니다.
이름 필드를 사용하여 인덱스 제거
컬렉션에서 제거인덱스를하려면 인덱스의 name
필드를 dropIndex()
메서드에 전달합니다.
인덱스 이름을 찾으려면 listIndexes()
메서드를 사용하여 인덱스의 name
필드 값을 확인합니다.
다음과 같은 스니펫은 컬렉션의 인덱스를 모두 검색하고 인쇄합니다.
collection.listIndexes().forEach(doc -> System.out.println(doc.toJson()));
텍스트 인덱스가 포함된 컬렉션에서 listIndex()
호출하는경우 출력은 다음과 같이 유사할 수 있습니다.
{ "v": 2, "key": {"_id": 1}, "name": "_id_" } { "v": 2, "key": {"_fts": "text", "_ftsx": 1}, "name": "title_text", "weights": {"title": 1}, "default_language": "english", "language_override": "language", "textIndexVersion": 3 }
이와 같은 출력은 기존 인덱스의 이름이 " _id " 및 " title_text " 임을 나타냅니다.
다음과 같은 스니펫은 컬렉션에서 "title_text" 인덱스를 제거합니다:
collection.dropIndex("title_text");
참고
복합 텍스트 인덱스에서 단일 필드를 제거할 수 없습니다. 인덱스된 필드를 업데이트하려면 인덱스를 전부 제거하고 새로운 인덱스를 생성해야 합니다.
와일드카드 문자를 사용하여 인덱스 제거
MongoDB 4.2부터 컬렉션에서 dropIndexes()
메서드를 호출하여 인댁스를 모두 제거할 수 있습니다.
collection.dropIndexes();
MongoDB 이전 버전의 경우 컬렉션의 dropIndex()
호출에 " * " 를 매개 변수로 전달합니다.
collection.dropIndex("*");
이 섹션의 메서드에 대한 자세한 내용은 다음 API 설명서를 참조하세요.