管理 Azure Cosmos DB 中的索引編製原則

適用於:NoSQL

Azure Cosmos DB 會遵循針對每個容器所定義的索引編製原則來為資料編製索引。 新建立的容器所套用的預設索引編製原則,會對任何字串或數字強制執行範圍索引。 您可以使用自己的自訂索引編製原則來覆寫此原則。

注意

本文所述的索引編製原則更新方法僅適用於 Azure Cosmos DB for NoSQL。 了解 Azure Cosmos DB for MongoDB 中的索引編製,和 Azure Cosmos DB for Apache Cassandra 中的次要索引編製

索引編製原則範例

以下幾個範例說明以 JSON 格式顯示的索引編製原則。 它們會以 JSON 格式公開於 Azure 入口網站上。 透過 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": "/*"
        }
    ]
}

注意

一般建議您使用選擇退出索引編製原則。 Azure Cosmos DB 會主動為任何可能新增至資料模型的新屬性編製索引。

僅對特定屬性路徑使用空間索引

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/_etag/?"
        }
    ],
    "spatialIndexes": [
        {
            "path": "/path/to/geojson/property/?",
            "types": [
                "Point",
                "Polygon",
                "MultiPolygon",
                "LineString"
            ]
        }
    ]
}

複合式索引編製原則範例

除了包含或排除個別屬性的路徑以外,您也可以指定複合式索引。 若要為多個屬性執行具有 ORDER BY 子句的查詢,必須要有這些屬性的複合式索引。 如果查詢包含篩選條件以及多個屬性的排序,您可能需要多個複合式索引。

對於有多個篩選條件的查詢或同時有篩選條件和 ORDER BY 子句的查詢,複合式索引也會有效能優勢。

注意

在複合路徑上,只會對純量值編製索引,因此複合路徑有隱含的 /?。 複合路徑中不支援 /* 萬用字元。 請勿在複合路徑中指定 /?/*。 複合路徑也會區分大小寫。

針對 (name asc, age desc) 定義的複合式索引

{  
    "automatic":true,
    "indexingMode":"Consistent",
    "includedPaths":[  
        {  
            "path":"/*"
        }
    ],
    "excludedPaths":[],
    "compositeIndexes":[  
        [  
            {  
                "path":"/name",
                "order":"ascending"
            },
            {  
                "path":"/age",
                "order":"descending"
            }
        ]
    ]
}

下列查詢需要 name 和 age 的複合式索引:

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

排除所有屬性路徑但讓索引編製保持作用狀態

存留時間 (TTL) 功能有作用,但不需要其他索引以將 Azure Cosmos DB 作為純粹索引鍵-值存放區的情況下,可以使用此原則。

{
    "indexingMode": "consistent",
    "includedPaths": [],
    "excludedPaths": [{
        "path": "/*"
    }]
}

無索引編製

此原則會關閉索引編製。 如果 indexingMode 設定為 none,您就無法在容器上設定 TTL。

{
    "indexingMode": "none"
}

更新索引編製原則

在 Azure Cosmos DB 中,您可以使用下列任何方法來更新索引編製原則:

  • 從 Azure 入口網站
  • 使用 Azure CLI
  • 使用 PowerShell
  • 使用其中一個 SDK

更新索引編製原則將會觸發索引的轉換。 您也可以從 SDK 追蹤此轉換的進度。

注意

當您更新索引編製原則時,對 Azure Cosmos DB 的寫入不會間斷。 深入了解索引編製轉換

重要

移除索引會立即生效,而新增索引需要一些時間,因為需要索引轉換。 將一個索引取代為另一個索引時 (例如,將單一屬性索引取代為複合式索引),請務必先新增新的索引,然後等候索引轉換完成,從索引編製原則中移除先前的索引。 否則,這會對查詢上一個索引的能力造成負面影響,並可能會中斷任何參考上一個索引的作用中工作負載。

使用 Azure 入口網站

Azure Cosmos DB 容器會將其索引編製原則儲存為 JSON 文件,並可直接在 Azure 入口網站中編輯。

  1. 登入 Azure 入口網站

  2. 建立新的 Azure Cosmos DB 帳戶或選取現有的帳戶。

  3. 開啟 [資料總管] 窗格,然後選取您要處理的容器。

  4. 選取 [調整與設定]

  5. 修改索引編製原則 JSON 文件,如這些範例所說明。

  6. 當完成時,選擇儲存

Manage Indexing using Azure portal

使用 Azure CLI

若要建立具有自訂索引編製原則的容器,請參閱使用 CLI 建立具有自訂索引原則的容器

使用 PowerShell

若要建立具有自訂索引編製原則的容器,請參閱使用 PowerShell 建立具有自訂索引原則的容器

使用 .NET SDK

.NET SDK v3 中的 ContainerProperties 物件會公開 IndexingPolicy 屬性,以供您變更 IndexingMode 以及新增或移除 IncludedPathsExcludedPaths。 如需詳細資訊,請參閱快速入門:適用於 .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);

若要追蹤索引的轉換進度,請傳遞 RequestOptions 物件並將其 PopulateQuotaInfo 屬性設定為 true。 從 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 物件可讓您變更索引編製模式,以及新增或移除已納入和排除的路徑。 如需詳細資訊,請參閱快速入門:建置 Java 應用程式以管理 Azure Cosmos DB for NoSQL 資料

// 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 以及新增或移除 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 屬性設定為 trueRequestOptions 物件。 從 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)

下一步

在下列文章中深入了解編製索引: