Azure Cosmos DB でインデックス作成ポリシーを管理する
Azure Cosmos DB では、コンテナーごとに定義されたインデックス作成ポリシーに従ってデータのインデックスが作成されます。 新しく作成したコンテナーの既定のインデックス作成ポリシーでは、文字列または数値に範囲インデックスが適用されます。 このポリシーは、独自のカスタム インデックス作成ポリシーでオーバーライドできます。
Note
この記事で説明するインデックス作成ポリシーの更新方法は、Azure Cosmos DB for NoSQL にのみ適用されます。 「Azure Cosmos DB for MongoDB」と「Azure Cosmos DB for Apache Cassandra でのセカンダリ インデックス作成」でインデックス作成について学習します。
インデックス作成ポリシーの例
JSON 形式で示されたインデックス作成ポリシーの例をいくつか以下に示します。 これらは JSON 形式で Azure portal で公開されます。 同じパラメーターは、Azure CLI のほか、任意の SDK で設定することができます。
一部のプロパティ パスを選択的に除外するオプトアウト ポリシー
{
"indexingMode": "consistent",
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/path/to/single/excluded/property/?"
},
{
"path": "/path/to/root/of/multiple/excluded/properties/*"
}
]
}
一部のプロパティ パスを選択的に包含するオプトイン ポリシー
{
"indexingMode": "consistent",
"includedPaths": [
{
"path": "/path/to/included/property/?"
},
{
"path": "/path/to/root/of/multiple/included/properties/*"
}
],
"excludedPaths": [
{
"path": "/*"
}
]
}
Note
一般に、''オプトアウト'' インデックス作成ポリシーを使用することをお勧めします。 Azure Cosmos DB では事前に、データ モデルに追加される可能性がある新しいプロパティのインデックスが作成されます。
特定のプロパティ パスに対してのみ空間インデックスを使用する
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/_etag/?"
}
],
"spatialIndexes": [
{
"path": "/path/to/geojson/property/?",
"types": [
"Point",
"Polygon",
"MultiPolygon",
"LineString"
]
}
]
}
ベクトル インデックス作成ポリシーの例
個々のプロパティのパスを含めたり除外したりするほかに、ベクトル インデックスを指定することもできます。 一般に、クエリ ベクトルとベクトル プロパティの類似度を測定するために VectorDistance
システム関数が使われているときは常に、ベクトル インデックスを指定する必要があります。
Note
先に進む前に、Azure Cosmos DB NoSQL ベクトル インデックス作成と検索 を有効にする必要があります。
重要
ベクトル インデックス作成ポリシーは、コンテナーのベクトル ポリシーで定義されている同じパス上に存在する必要があります。 コンテナーのベクトル ポリシーの詳細を参照してください。
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/_etag/?"
},
{
"path": "/vector/*"
}
],
"vectorIndexes": [
{
"path": "/vector",
"type": "quantizedFlat"
}
]
}
重要
挿入の最適なパフォーマンスを確保するためにインデックス作成ポリシーの "excludedPaths" セクションに追加されたベクトル パス。 ベクトル パスを "excludedPaths" に追加しないと、ベクトル挿入に対してより高い RU 料金と待機時間が発生します。
重要
現在、ベクトル ポリシーとベクトル インデックスは、作成後に変更できません。 変更するには、新しいコレクションを作成してください。
次の種類のベクトル インデックス ポリシーを定義できます。
型 | 説明 | 最大ディメンション |
---|---|---|
flat |
他のインデックス プロパティと同じインデックスにベクトルを格納します。 | 505 |
quantizedFlat |
インデックスに格納する前にベクトルを量子化 (圧縮) します。 これにより、わずかな精度を犠牲にして、待機時間とスループットを向上させることができます。 | 4096 |
diskANN |
高速かつ効率的な概算検索のために、DiskANN に基づいてインデックスを作成します。 | 4096 |
flat
と quantizedFlat
のインデックスの種類は、ベクトル検索を実行するときに、Azure Cosmos DB のインデックスを使って、各ベクトルの格納と読み取りを行います。 flat
インデックスを使用するベクトル検索はブルート フォース検索であり、100% の精度を実現します。 ただし、フラット インデックス上のベクトルには 505
ディメンションの制限があります。
quantizedFlat
インデックスは、量子化つまり圧縮されたベクトルをインデックスに格納します。 quantizedFlat
インデックスを使用したベクトル検索もブルート フォース検索ですが、インデックスに追加する前にベクトルが量子化されるため、精度は 100% をわずかに下回る可能性があります。 ただし、quantized flat
を使用したベクトル検索は flat
インデックスでのベクトル検索よりも待機時間が短く、スループットが高く、RU コストが低くなります。 これは、クエリ フィルターを使ってベクトル検索を比較的小さなベクトル セットに絞り込むシナリオに適したオプションです。
diskANN
インデックスは、Microsoft Research によって開発されたハイ パフォーマンス ベクトル インデックス作成アルゴリズム スイートである DiskANN を使用する、ベクトル専用に定義された個別のインデックスです。 DiskANN インデックスは、最短の待ち時間、最高の 1 秒あたりクエリ数 (QPS)、最小の RU コスト クエリを、高い精度で提供できます。 ただし、DiskANN は近似ニアレストネイバー (ANN) インデックスであるため、精度は quantizedFlat
や flat
よりも低くなる可能性があります。
diskANN
と quantizedFlat
インデックスは、すべての近似最近傍ベクトル インデックスに適用される精度と待機時間のトレードオフを調整するために使用できる、オプションのインデックス構築パラメーターを取ることができます。
quantizationByteSize
: 直積量子化のサイズ (バイト単位) を設定します。 最小値 = 1、規定値 = 動的 (システムが決定)、最大値 = 512。 この値が高いほど、RU コストが高くなり、待機時間が長くなる代わりに、ベクトル検索の精度が高くなる可能性があります。 これは、quantizedFlat
とDiskANN
の両方のインデックスの種類に適用されます。indexingSearchListSize
: インデックスの構築中に検索するベクトルの数を設定します。 最小値 = 10、規定値 = 100、最大値 = 500。 この値が高いほど、インデックスのビルド時間が長くなり、ベクトルの取り込みの待機時間が長くなる代わりに、ベクトル検索の精度が高くなる可能性があります。 これは、DiskANN
インデックスにのみ適用されます。
タプル インデックス作成ポリシーの例
このインデックス作成ポリシーの例では、events.name と events.category にタプル インデックスを定義します
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{"path":"/*"},
{"path":"/events/[]/{name,category}/?"}
],
"excludedPaths":[],
"compositeIndexes":[]
}
上記のインデックスは、次のクエリに使用されます。
SELECT *
FROM root r
WHERE
EXISTS (SELECT VALUE 1 FROM ev IN r.events
WHERE ev.name = ‘M&M’ AND ev.category = ‘Candy’)
複合インデックス作成ポリシーの例
個々のプロパティのパスを含めたり除外したりするほかに、複合インデックスを指定することもできます。 複数のプロパティに対して 1 つの ORDER BY
句を使用するクエリを実行するには、これらのプロパティに対する複合インデックスが必要になります。 クエリに複数のプロパティの並べ替えと共にフィルターが含まれている場合は、複数の複合インデックスが必要になる場合があります。
複合インデックスには、複数のフィルターや、1 つのフィルターと 1 つの ORDER BY 句の両方があるクエリでパフォーマンス上の利点もあります。
Note
複合パスではスカラー値のインデックスのみが作成されるため、そのパスには /?
が暗黙的に含まれています。 複合パスでは /*
ワイルドカードはサポートされません。 複合パスに /?
または /*
を指定しないでください。 複合パスでも大文字と小文字が区別されます。
(name asc, age desc) に対して定義された複合インデックス
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[],
"compositeIndexes":[
[
{
"path":"/name",
"order":"ascending"
},
{
"path":"/age",
"order":"descending"
}
]
]
}
次のクエリでは、名前と年齢の複合インデックスが必要です。
クエリ #1:
SELECT *
FROM c
ORDER BY c.name ASC, c.age DESC
クエリ #2:
SELECT *
FROM c
ORDER BY c.name DESC, c.age ASC
この複合インデックスでは、次のクエリで利点が得られ、フィルターが最適化されます。
クエリ #3:
SELECT *
FROM c
WHERE c.name = "Tim"
ORDER BY c.name DESC, c.age ASC
クエリ #4:
SELECT *
FROM c
WHERE c.name = "Tim" AND c.age > 18
(name ASC, age ASC) と (name ASC, age DESC) に定義されている複合インデックス
同じインデックス作成ポリシー内で複数の複合インデックスを定義できます。
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[],
"compositeIndexes":[
[
{
"path":"/name",
"order":"ascending"
},
{
"path":"/age",
"order":"ascending"
}
],
[
{
"path":"/name",
"order":"ascending"
},
{
"path":"/age",
"order":"descending"
}
]
]
}
(name ASC, age ASC) に定義されている複合インデックス
順序の指定は任意です。 指定されていない場合、順序は昇順です。
{
"automatic":true,
"indexingMode":"Consistent",
"includedPaths":[
{
"path":"/*"
}
],
"excludedPaths":[],
"compositeIndexes":[
[
{
"path":"/name"
},
{
"path":"/age"
}
]
]
}
インデックス作成をアクティブ状態に保ちながらすべてのプロパティ パスを除外する
このポリシーは、Time-to-Live (TTL) 機能がアクティブであるものの、Azure Cosmos DB を純粋なキー値ストアとして使用するための他のインデックスは不要である場合に使用できます。
{
"indexingMode": "consistent",
"includedPaths": [],
"excludedPaths": [{
"path": "/*"
}]
}
インデックス作成なし
このポリシーによってインデックス作成がオフになります。 indexingMode
が none
に設定されている場合、コンテナーで TTL を設定することはできません。
{
"indexingMode": "none"
}
インデックス作成ポリシーの更新
Azure Cosmos DB では、インデックス作成ポリシーは次のいずれかの方法を使用して更新できます。
- Azure portal から
- Azure CLI の使用
- PowerShell の使用
- SDK のいずれかを使用する
インデックス作成ポリシーの更新により、インデックスの変換がトリガーされます。 この変換の進行状況は、SDK から追跡することもできます。
Note
インデックス作成ポリシーを更新するときに、Azure Cosmos DB への書き込みは中断されません。 インデックスの変換の詳細を確認してください。
重要
インデックスの削除は直ちに反映されますが、新しいインデックスの追加は、インデックス作成変換が必要であるため、しばらく時間がかかります。 1 つのインデックスを別のインデックスに置き換える場合 (たとえば、単一のプロパティ インデックスを複合インデックスに置き換える場合)、まず新しいインデックスを最初に追加し、インデックスの変換が完了するのを待ってから、以前のインデックスをインデックス作成ポリシーから削除するようにしてください。 そうしないと、前のインデックスに対してクエリを実行する機能に悪影響が及び、前のインデックスを参照するアクティブなワークロードが中断される可能性があります。
Azure ポータルの使用
Azure Cosmos DB のコンテナーには、そのインデックス作成ポリシーが Azure portal で直接編集できる JSON ドキュメントとして格納されます。
Azure portal にサインインします。
新しい Azure Cosmos DB アカウントを作成するか、既存のアカウントを選びます。
[データ エクスプローラー] ウィンドウを開いて、操作の対象となるコンテナーを選択します。
[スケールと設定] を選択します。
これらの例に示すように、インデックス作成ポリシーの JSON ドキュメントを変更します。
完了したら、 [保存] を選択します。
Azure CLI の使用
カスタム インデックス作成ポリシーを使用してコンテナーを作成する場合は、CLI を使用したカスタム インデックス作成ポリシーでのコンテナーの作成に関する説明を参照してください。
PowerShell の使用
カスタム インデックス作成ポリシーを使用してコンテナーを作成する場合は、PowerShell を使用したカスタム インデックス作成ポリシーでのコンテナーの作成に関する説明を参照してください。
.NET SDK を使用する
.NET SDK v3 の ContainerProperties
オブジェクトでは、IndexingMode
を変更し、IncludedPaths
および ExcludedPaths
を追加または削除できる IndexingPolicy
プロパティを公開しています。 詳細については、「クイック スタート: .NET 用の Azure Cosmos DB for NoSQL クライアント ライブラリ」を参照してください。
// Retrieve the container's details
ContainerResponse containerResponse = await client.GetContainer("database", "container").ReadContainerAsync();
// Set the indexing mode to consistent
containerResponse.Resource.IndexingPolicy.IndexingMode = IndexingMode.Consistent;
// Add an included path
containerResponse.Resource.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
// Add an excluded path
containerResponse.Resource.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/name/*" });
// Add a spatial index
SpatialPath spatialPath = new SpatialPath
{
Path = "/locations/*"
};
spatialPath.SpatialTypes.Add(SpatialType.Point);
containerResponse.Resource.IndexingPolicy.SpatialIndexes.Add(spatialPath);
// Add a composite index
containerResponse.Resource.IndexingPolicy.CompositeIndexes.Add(new Collection<CompositePath> { new CompositePath() { Path = "/name", Order = CompositePathSortOrder.Ascending }, new CompositePath() { Path = "/age", Order = CompositePathSortOrder.Descending } });
// Update container with changes
await client.GetContainer("database", "container").ReplaceContainerAsync(containerResponse.Resource);
インデックス変換の進行状況を追跡するには、PopulateQuotaInfo
プロパティを true
に設定する RequestOptions
オブジェクトを渡します。 x-ms-documentdb-collection-index-transformation-progress
応答ヘッダーから値を取得します。
// retrieve the container's details
ContainerResponse containerResponse = await client.GetContainer("database", "container").ReadContainerAsync(new ContainerRequestOptions { PopulateQuotaInfo = true });
// retrieve the index transformation progress from the result
long indexTransformationProgress = long.Parse(containerResponse.Headers["x-ms-documentdb-collection-index-transformation-progress"]);
新しいコンテナーの作成中にカスタム インデックス作成ポリシーを定義すると、SDK V3 fluent API によって、この定義を簡潔かつ効率的な方法で記述できます。
await client.GetDatabase("database").DefineContainer(name: "container", partitionKeyPath: "/myPartitionKey")
.WithIndexingPolicy()
.WithIncludedPaths()
.Path("/*")
.Attach()
.WithExcludedPaths()
.Path("/name/*")
.Attach()
.WithSpatialIndex()
.Path("/locations/*", SpatialType.Point)
.Attach()
.WithCompositeIndex()
.Path("/name", CompositePathSortOrder.Ascending)
.Path("/age", CompositePathSortOrder.Descending)
.Attach()
.Attach()
.CreateIfNotExistsAsync();
Java SDK の使用
Java SDK の DocumentCollection
オブジェクトでは、getIndexingPolicy()
および setIndexingPolicy()
メソッドを公開しています。 これらによって操作される IndexingPolicy
オブジェクトを使用すると、インデックス作成モードを変更したり、対象のパスと対象外のパスを追加または削除したりすることができます。 詳細については、「クイック スタート: Azure Cosmos DB for NoSQL のデータを管理するための Java アプリを作成する」を参照してください。
// Retrieve the container's details
Observable<ResourceResponse<DocumentCollection>> containerResponse = client.readCollection(String.format("/dbs/%s/colls/%s", "database", "container"), null);
containerResponse.subscribe(result -> {
DocumentCollection container = result.getResource();
IndexingPolicy indexingPolicy = container.getIndexingPolicy();
// Set the indexing mode to consistent
indexingPolicy.setIndexingMode(IndexingMode.Consistent);
// Add an included path
Collection<IncludedPath> includedPaths = new ArrayList<>();
IncludedPath includedPath = new IncludedPath();
includedPath.setPath("/*");
includedPaths.add(includedPath);
indexingPolicy.setIncludedPaths(includedPaths);
// Add an excluded path
Collection<ExcludedPath> excludedPaths = new ArrayList<>();
ExcludedPath excludedPath = new ExcludedPath();
excludedPath.setPath("/name/*");
excludedPaths.add(excludedPath);
indexingPolicy.setExcludedPaths(excludedPaths);
// Add a spatial index
Collection<SpatialSpec> spatialIndexes = new ArrayList<SpatialSpec>();
Collection<SpatialType> collectionOfSpatialTypes = new ArrayList<SpatialType>();
SpatialSpec spec = new SpatialSpec();
spec.setPath("/locations/*");
collectionOfSpatialTypes.add(SpatialType.Point);
spec.setSpatialTypes(collectionOfSpatialTypes);
spatialIndexes.add(spec);
indexingPolicy.setSpatialIndexes(spatialIndexes);
// Add a composite index
Collection<ArrayList<CompositePath>> compositeIndexes = new ArrayList<>();
ArrayList<CompositePath> compositePaths = new ArrayList<>();
CompositePath nameCompositePath = new CompositePath();
nameCompositePath.setPath("/name");
nameCompositePath.setOrder(CompositePathSortOrder.Ascending);
CompositePath ageCompositePath = new CompositePath();
ageCompositePath.setPath("/age");
ageCompositePath.setOrder(CompositePathSortOrder.Descending);
compositePaths.add(ageCompositePath);
compositePaths.add(nameCompositePath);
compositeIndexes.add(compositePaths);
indexingPolicy.setCompositeIndexes(compositeIndexes);
// Update the container with changes
client.replaceCollection(container, null);
});
コンテナーに対するインデックス変換の進行状況を追跡するには、クォータ情報の読み込みを要求する RequestOptions
オブジェクトを渡します。 x-ms-documentdb-collection-index-transformation-progress
応答ヘッダーから値を取得します。
// set the RequestOptions object
RequestOptions requestOptions = new RequestOptions();
requestOptions.setPopulateQuotaInfo(true);
// retrieve the container's details
Observable<ResourceResponse<DocumentCollection>> containerResponse = client.readCollection(String.format("/dbs/%s/colls/%s", "database", "container"), requestOptions);
containerResponse.subscribe(result -> {
// retrieve the index transformation progress from the response headers
String indexTransformationProgress = result.getResponseHeaders().get("x-ms-documentdb-collection-index-transformation-progress");
});
Node.js SDK の使用
Node.js SDK の ContainerDefinition
インターフェイスでは indexingPolicy
プロパティを公開しています。これを使用すると、indexingMode
を変更したり、includedPaths
や excludedPaths
を追加または削除したりすることができます。 詳細については、「クイック スタート: Node.js 用の Azure Cosmos DB for NoSQL クライアント ライブラリ」を参照してください。
コンテナーの詳細を取得する:
const containerResponse = await client.database('database').container('container').read();
インデックス作成モードを同期に設定する:
containerResponse.body.indexingPolicy.indexingMode = "consistent";
空間インデックスを含む対象パスを追加する:
containerResponse.body.indexingPolicy.includedPaths.push({
includedPaths: [
{
path: "/age/*",
indexes: [
{
kind: cosmos.DocumentBase.IndexKind.Range,
dataType: cosmos.DocumentBase.DataType.String
},
{
kind: cosmos.DocumentBase.IndexKind.Range,
dataType: cosmos.DocumentBase.DataType.Number
}
]
},
{
path: "/locations/*",
indexes: [
{
kind: cosmos.DocumentBase.IndexKind.Spatial,
dataType: cosmos.DocumentBase.DataType.Point
}
]
}
]
});
対象外パスを追加する:
containerResponse.body.indexingPolicy.excludedPaths.push({ path: '/name/*' });
変更に従ってコンテナーを更新する:
const replaceResponse = await client.database('database').container('container').replace(containerResponse.body);
コンテナーに対するインデックス変換の進行状況を追跡するには、populateQuotaInfo
プロパティを true
に設定する RequestOptions
オブジェクトを渡します。 x-ms-documentdb-collection-index-transformation-progress
応答ヘッダーから値を取得します。
// retrieve the container's details
const containerResponse = await client.database('database').container('container').read({
populateQuotaInfo: true
});
// retrieve the index transformation progress from the response headers
const indexTransformationProgress = replaceResponse.headers['x-ms-documentdb-collection-index-transformation-progress'];
複合インデックスを追加する:
console.log("create container with composite indexes");
const containerDefWithCompositeIndexes = {
id: "containerWithCompositeIndexingPolicy",
indexingPolicy: {
automatic: true,
indexingMode: IndexingMode.consistent,
includedPaths: [
{
path: "/*",
},
],
excludedPaths: [
{
path: '/"systemMetadata"/*',
},
],
compositeIndexes: [
[
{ path: "/field", order: "ascending" },
{ path: "/key", order: "ascending" },
],
],
},
};
const containerWithCompositeIndexes = (
await database.containers.create(containerDefWithCompositeIndexes)
).container;
Python SDK の使用
Python SDK V3 を使用する場合、コンテナーの構成はディクショナリとして管理されます。 このディクショナリから、インデックス作成ポリシーとそのすべての属性にアクセスすることができます。 詳細については、「クイック スタート: Python 用の Azure Cosmos DB for NoSQL クライアント ライブラリ」を参照してください。
コンテナーの詳細を取得する:
containerPath = 'dbs/database/colls/collection'
container = client.ReadContainer(containerPath)
インデックス作成モードを同期に設定する:
container['indexingPolicy']['indexingMode'] = 'consistent'
対象パスと空間インデックスと共にインデックス作成ポリシーを定義する:
container["indexingPolicy"] = {
"indexingMode":"consistent",
"spatialIndexes":[
{"path":"/location/*","types":["Point"]}
],
"includedPaths":[{"path":"/age/*","indexes":[]}],
"excludedPaths":[{"path":"/*"}]
}
対象外パスと共にインデックス作成ポリシーを定義する:
container["indexingPolicy"] = {
"indexingMode":"consistent",
"includedPaths":[{"path":"/*","indexes":[]}],
"excludedPaths":[{"path":"/name/*"}]
}
複合インデックスを追加する:
container['indexingPolicy']['compositeIndexes'] = [
[
{
"path": "/name",
"order": "ascending"
},
{
"path": "/age",
"order": "descending"
}
]
]
変更に従ってコンテナーを更新する:
response = client.ReplaceContainer(containerPath, container)