スレッド処理と並列処理を実装する

完了

SDK では、スレッド セーフなタイプとある程度の並列処理を実装しますが、ワークロードで発揮できる最適なパフォーマンスを SDK で出せるように、アプリケーション コードに実装できるベスト プラクティスがあります。

多くの場合、サービス側の問題ではなく、クライアント コンピューターでの CPU またはポートの使用率が高いため、要求タイムアウトが発生します。 ローカル リソースの枯渇による SDK エラーや再試行を回避するには、クライアント マシンでのリソース使用率を監視し、適切にスケールアウトすることが重要です。

.NET で async/await を使用する

.NET の C# 言語には、SDK クライアント メソッドを非同期に呼び出す一連のタスクベースの機能が用意されています。 たとえば、CreateDatabaseIfNotExistsAsync メソッドは、次の構文を使用して非同期的に呼び出されます。

Database database = await client.CreateDatabaseIfNotExistsAsync("cosmicworks");

この構文では、awaited キーワードを使用してタスクを非同期的に実行し、指定された変数に結果を返します。 非同期キーワードを使用すると、SDK による、要求の効率的な同時管理が可能となります。

非同期実行をブロックしないように、次のコード例で示されているTask.WaitまたはTask.Resultの使用を避けてください。

Database database = client.CreateDatabaseIfNotExistsAsync("cosmicworks").Result;

LINQ メソッドではなく、組み込みの反復子を使用する

ToList などの LINQ メソッドは、他の呼び出しの実行をブロックしながら、クエリを積極的かつ同期的に完了させます。 たとえば、この ToList() の呼び出しは、他のすべての呼び出しをブロックし、大量のデータセットを取得する可能性があります。

container.GetItemLinqQueryable<T>()
    .Where(i => i.categoryId == 2)
    .ToList<T>();

SDK には、他の呼び出しをブロックせずにクエリの結果を非同期に取得するToFeedIterator<T> などのメソッドが含まれています。 この例は、同じシナリオを示していますが、ToList の代わりに特別な反復子を使用しています。

container.GetItemLinqQueryable<T>()
    .Where(i => i.categoryId == 2)
    .ToFeedIterator<T>();

最大コンカレンシー、並列処理、バッファー項目数を構成する

SDK からクエリを発行する場合、 QueryRequestOptions には、クエリのパフォーマンスを調整するための一連のプロパティが含まれます。

最大項目数

Azure Cosmos DB for NoSQL のすべてのクエリ結果は、結果の "ページ" として返されます。 このプロパティは、各 "ページ" で返される項目の数を示します。 サービスの既定値は、結果のページごとに 100 項目です。 この値を -1 に設定すると、動的ページ サイズを設定できます。

この例では、MaxItemCount プロパティの値は 500 に設定されています。

QueryRequestOptions options = new ()
{
    MaxItemCount = 500
};

ヒント

-1 の MaxItemCount を使用する場合は、応答サイズのサービス制限を超えないようにする必要があります。 たとえば、最大応答サイズは 4 MB です。

最大コンカレンシー

MaxConcurrency では、並列クエリの実行中にクライアント側で実行された同時実行操作の数を指定します。 1 に設定すると、並列処理は実質的に無効になります。 -1 に設定すると、SDK はこの設定を管理します。 この値は、コンテナーの物理パーティションの数に設定するのが理想的です。

この例では、MaxItemCount プロパティの値は 5 に設定されています。

QueryRequestOptions options = new ()
{
    MaxConcurrency = 5
};

最大バッファー項目数

MaxBufferedItemCount プロパティでは、並列クエリの実行中にクライアント側でバッファーされる項目の最大数を設定します。 -1 に設定すると、SDK はこの設定を管理します。 この設定の理想的な値は、クライアント コンピューターの特性によって大きく異なります。

この例では、MaxBufferedItemCount プロパティの値は 5,000 に設定されています。

QueryRequestOptions options = new ()
{
    MaxBufferedItemCount = 5000
};

Azure Cosmos DB Python SDK を使用してワークロードに最適なパフォーマンスを確保するときに、Python アプリケーションに実装できるベスト プラクティスとオプションがいくつかあります。

多くの要求タイムアウトは、Azure Cosmos DB サービス側で発生する問題ではなく、クライアント コンピューターでの CPU 使用率またはリソース使用率が高いために発生します。 クライアント マシンでのリソース使用量を監視し、アプリケーションを適切にスケールアウトして、ローカル リソースの枯渇による SDK エラーや再試行を回避します。

非同期クエリを使用する

Azure Cosmos DB Python SDK は、Python の asyncio フレームワークを介した非同期操作をサポートし、 azure.cosmos.aio 名前空間での非同期プログラミングのクラスを提供します。 たとえば、query_items メソッドを非同期的に使用できます。

from azure.cosmos.aio import CosmosClient
import asyncio

endpoint = "<cosmos-endpoint>"
key = "<cosmos-key>"

client = CosmosClient(endpoint, key)

async def query_items_async(client):
    # Get database and container clients
    database = client.get_database_client("cosmicworks")
    container = database.get_container_client("products")

    # Define the query and parameters
    query = "SELECT * FROM c WHERE c.categoryId = @categoryId"
    parameters = [{"name": "@categoryId", "value": "bikes"}]

    # Perform the query asynchronously
    async for item in container.query_items(
        query=query,
        parameters=parameters
    ):
        print(item)

    # Close the client
    await client.close()

asyncio.run(query_items_async(client))

非同期操作に azure.cosmos.aio クラスを使用する前に、 aiohttp ライブラリ (pip install aiohttp) がインストールされていることを確認してください。

asyncioを使用すると、他のコードの実行をブロックすることなく、複数の操作を同時に処理できます。

次のような同期メソッドと非同期メソッドを不適切に混在させて非同期実行をブロックしないようにします。

iterator = client.query_items(query=query, parameters=parameters).result()  # Incorrect

代わりに、非同期呼び出しには常に await を使用してください。

クエリに反復子を使用する

Python SDK には、他の操作をブロックすることなくクエリ結果を効率的に取得するための反復子が組み込まれています。 メモリ使用量が大きくなり、他の操作がブロックされる可能性があるため、すべてのクエリ結果を一括して収集することは避けてください。

非効率的な例:

results = list(container.query_items(
    query="SELECT * FROM c WHERE c.categoryId = 'bikes'"
))

反復子を使用した効率的な例:

iterator = container.query_items(
    query="SELECT * FROM c WHERE c.categoryId = 'bikes'"
)

async for item in iterator:
    print(item)

反復子を使用すると、メモリ効率の高い方法でデータを処理し、到着した結果を処理できます。

パフォーマンスのクエリ オプションを構成する

クエリを発行する場合、Python SDK では、パフォーマンスを向上させるために、 QueryIterable または query_items メソッドを使用していくつかのオプションを構成できます。

最大項目数

Azure Cosmos DB for NoSQL のすべてのクエリ結果は、結果の "ページ" で返されます。 max_item_count パラメーターは、各ページで返される項目の数を指定します。 サービスの既定値は、1 ページあたり 100 アイテムです。

500 のmax_item_countを使用した例:

iterator = container.query_items(
    query="SELECT * FROM c",
    max_item_count=500
)

ヒント

max_item_count-1 を使用する場合は、応答サイズの合計が 4 MB のサービスの制限を超えないようにします。

パーティション キーの使用法

可能な限り、クエリ フィルターにパーティション キーを含めます。 このパーティション キーを使用すると、クエリ スコープが 1 つのパーティションに減り、パフォーマンスが大幅に向上します。

例:

iterator = container.query_items(
    query="SELECT * FROM c WHERE c.categoryId = @categoryId",
    parameters=[{"name": "@categoryId", "value": "bikes"}],
    partition_key="bikes"
)

バッチ操作を実行する

Python SDK では、同じパーティション キー内の項目に対するバッチ操作が可能です。 TransactionalBatch クラスを使用して、複数の操作を原子性で実行します。

例:

# Define the partition key and batch operations
partition_key = "socks"
batch = [
    ("create", ({"id": "sock7", "categoryId": partition_key, "name": "Red Racing Socks"},)),
    ("create", ({"id": "sock8", "categoryId": partition_key, "name": "White Racing Socks"},))
]

# Execute the batch
batch_response = container.execute_item_batch(batch, partition_key=partition_key)

# Print the resource body results to see the created items
for result in batch_response:
    print(result.get("resourceBody"))

注釈

バッチ操作は 1 つのパーティション キーを対象とする必要があり、最大 100 操作または 4 MB のサイズを含めることができます。

Azure Cosmos DB JavaScript SDK を使用してワークロードに最適なパフォーマンスを確保するときに、アプリケーションに実装できるベスト プラクティスとオプションがいくつかあります。

要求タイムアウトは、多くの場合、サービス側の問題ではなく、クライアント コンピューターでの CPU 使用率またはリソース使用率が高いために発生します。 クライアント コンピューターでのリソースの使用状況を監視し、アプリケーションを適切にスケールアウトして、ローカル リソースの枯渇による SDK エラーや再試行を回避します。

非同期クエリを使用する

Azure Cosmos DB JavaScript SDK では、Promise と async/await を使用した非同期操作がサポートされています。 たとえば、createDatabaseIfNotExists メソッドを非同期的に使用できます。

const { CosmosClient } = require("@azure/cosmos");

const client = new CosmosClient({ endpoint: "<cosmos-endpoint>", key: "<cosmos-key>" });

async function createDatabase() {
    const { database } = await client.databases.createIfNotExists({ id: "cosmicworks" });
    console.log(`Database created: ${database.id}`);
}
createDatabase();

async/awaitを使用すると、非ブロッキング操作が保証され、SDK が複数の要求を効率的に処理できるようになります。

パフォーマンスを妨げる方法で .then() または .catch() を不適切に使用して非同期実行をブロックしないようにします。

クエリに反復子を使用する

JavaScript SDK には、他の操作をブロックすることなくクエリ結果を効率的に取得するための反復子が組み込まれています。 大量のメモリを消費し、他の操作をブロックする可能性があるため、すべてのクエリ結果を熱心に収集することは避けてください。

非効率的な例

const results = await container.items
    .query("SELECT * FROM c WHERE c.categoryId = 2", { enableCrossPartitionQuery: true })
    .fetchAll();
console.log(results.resources);

反復子を使用した効率的な例

const iterator = container.items.query(
    "SELECT * FROM c WHERE c.categoryId = 2",
    { enableCrossPartitionQuery: true }
);

while (iterator.hasMoreResults()) {
    const { resources } = await iterator.fetchNext();
    for (const item of resources) {
        console.log(item);
    }
}

反復子を使用すると、結果を小さなバッチで処理できるため、メモリ使用量が減り、効率が向上します。

パフォーマンスのクエリ オプションを構成する

クエリを発行する場合、JavaScript SDK では、#D0 メソッドを使用していくつかのオプションを構成してパフォーマンスを向上させることができます。

最大項目数

Azure Cosmos DB for NoSQL のすべてのクエリ結果は、結果の "ページ" で返されます。 maxItemCount パラメーターは、各ページで返される項目の数を指定します。 サービスの既定値は、1 ページあたり 100 アイテムです。

500 のmaxItemCountを使用した例:

const iterator = container.items.query(
    "SELECT * FROM c",
    { maxItemCount: 500, enableCrossPartitionQuery: true }
);

ヒント

maxItemCount-1 を使用する場合は、応答サイズの合計が 4 MB のサービスの制限を超えないようにします。

パーティション キーの使用法

可能な限り、クエリ フィルターにパーティション キーを含めます。 このパーティション キーを使用すると、クエリ スコープが 1 つのパーティションに減り、パフォーマンスが大幅に向上します。

例:

const iterator = container.items.query(
    {
        query: "SELECT * FROM c WHERE c.categoryId = @categoryId",
        parameters: [{ name: "@categoryId", value: "socks" }]
    },
    { partitionKey: "socks" }
);

categoryIdはパーティション キーでもあるため、簡略化された構文を使用することもできます。

const iterator = container.items.query(
    {
        query: "SELECT * FROM c"
    },
    { partitionKey: "socks" }
);

バッチ操作を実行する

JavaScript SDK では、同じパーティション キー内の項目に対するバッチ操作が可能です。 container.items.batch メソッドを使用して、複数の操作をアトミックに実行します。

例:

const { CosmosClient, BulkOperationType } = require("@azure/cosmos");

const partitionKey = "bikes";
    const operations = [
        {
            operationType: BulkOperationType.Create,
            resourceBody: {
                id: "rb3k",
                name: "Road Bike 3000",
                description: "This is a very fast road bike.",
                categoryId: "bikes"
            }
        },
        {
            operationType: BulkOperationType.Create,
            resourceBody: {
                id: "mb2k",
                name: "Mountain Bike 2000",
                description: "This is a capable and sturdy mountain bike.",
                categoryId: "bikes"
            }
        },
        {
            operationType: BulkOperationType.Create,
            resourceBody: {
                id: "tb1k",
                name: "Touring Bike 1000",
                description: "This is a casual touring bike.",
                categoryId: "bikes"
            }
        }
    ];

    const response = await container.items
        .bulk(operations, { partitionKey });
    console.log(response);

注釈

バッチ操作は 1 つのパーティション キーを対象とする必要があり、最大 100 操作または 2 MB のサイズを含めることができます。

注釈

これらの設定については、SDK を使用したクエリの発行に関する他の Azure Cosmos DB for NoSQL モジュールで詳しく説明します。