Azure Cosmos DB でインデックス作成ポリシーを管理する

適用対象: NoSQL

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"
            ]
        }
    ]
}

複合インデックス作成ポリシーの例

個々のプロパティのパスを含めたり除外したりするほかに、複合インデックスを指定することもできます。 複数のプロパティに対して 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": "/*"
    }]
}

インデックス作成なし

このポリシーによってインデックス作成がオフになります。 indexingModenone に設定されている場合、コンテナーで 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 ドキュメントとして格納されます。

  1. Azure portal にサインインします。

  2. 新しい Azure Cosmos DB アカウントを作成するか、既存のアカウントを選びます。

  3. [データ エクスプローラー] ウィンドウを開いて、操作の対象となるコンテナーを選択します。

  4. [スケールと設定] を選択します。

  5. これらのに示すように、インデックス作成ポリシーの JSON ドキュメントを変更します。

  6. 完了したら、 [保存] を選択します。

Manage Indexing using Azure portal

Azure CLI の使用

カスタム インデックス作成ポリシーを使用してコンテナーを作成する場合は、CLI を使用したカスタム インデックス作成ポリシーでのコンテナーの作成に関する説明を参照してください。

PowerShell の使用

カスタム インデックス作成ポリシーを使用してコンテナーを作成する場合は、PowerShell を使用したカスタム インデックス作成ポリシーでのコンテナーの作成に関する説明を参照してください。

.NET SDK を使用する

.NET SDK v3ContainerProperties オブジェクトでは、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 SDKDocumentCollection オブジェクトでは、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 SDKContainerDefinition インターフェイスでは indexingPolicy プロパティを公開しています。これを使用すると、indexingMode を変更したり、includedPathsexcludedPaths を追加または削除したりすることができます。 詳細については、「クイック スタート: 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'];

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)

次のステップ

以下の記事で、インデックス作成についての詳細を参照してください。