すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:OSS データインデックスを用いた大規模データ統計

最終更新日:Mar 21, 2026

OSS データインデックスにより、単一の API 呼び出しで数億個に及ぶオブジェクトに対してクエリ実行および集約統計処理が可能です。従来の `ListObjects` のページネーションによる反復呼び出しは不要です。

本チュートリアルでは、以下の手順を実施します。

  1. コンソールまたは SDK を使用して、バケットでデータインデックスを有効化します。

  2. フィルター(プレフィックス、ストレージクラス、アクセス制御リスト (ACL))および集約操作(合計サイズ、平均サイズ、オブジェクト数)を指定したクエリを実行します。

  3. 結果が期待される出力と一致することを確認します。

仕組み

バケットでデータインデックスを有効化すると、OSS はそのバケット内のオブジェクトのメタデータ、ユーザーメタデータ、およびオブジェクトタグに基づいてインデックステーブルを構築します。インデックス作成後は、JSON 形式のクエリ式および集約定義を含む `DoMetaQuery` 操作を呼び出します。OSS はこのクエリをインデックステーブルに対して評価し、対象となるオブジェクトおよび集約統計結果を返却します。この際、バケット内のオブジェクトを 1 つずつスキャンする必要はありません。

image

パフォーマンス比較(Enterprise A:バケット `mybucket` 内のオブジェクト数 2 億個、ディレクトリ数 180 万個、リージョン:中国 (広州)):

指標ListObjects(従来方式)データインデックス
1 日あたりの処理時間2 時間20 分
ディレクトリあたりの API 呼び出し回数(オブジェクト数 > 1,000 個)複数回の `ListObjects` 呼び出し1 回の `DoMetaQuery` 呼び出し

データインデックスにより、統計収集時間が 83 % 短縮されました。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

  • OSS バケットに既にオブジェクトがアップロード済みであること

  • 環境変数 `OSS_ACCESS_KEY_ID` および `OSS_ACCESS_KEY_SECRET` が設定されており、`OpenMetaQuery` および `DoMetaQuery` の呼び出し権限を持つ認証情報が含まれていること

  • (SDK のみ)Java、Python、または Go 向け OSS SDK がインストール済みであること(データインデックス(MetaSearch)機能をサポートするのはこれらの SDK のみ)

手順 1:データインデックスの有効化

OSS コンソールを使用する

  1. OSS コンソール にログインします。

  2. 左側ナビゲーションウィンドウで、バケット をクリックします。バケット一覧ページで、データインデックスを有効化するバケット名をクリックします。

  3. 左側ナビゲーションツリーで、オブジェクト管理データインデックス を選択します。

  4. データインデックス ページで、今すぐ有効化 をクリックします。

  5. データインデックスダイアログボックスで、MetaSearch を選択し、有効化 をクリックします。

OSS SDK を使用する

以下のすべての例では、機能の有効化に `OpenMetaQuery`(Java/Go)または `open_bucket_meta_query`(Python)を呼び出します。認証情報は環境変数から読み込まれます。

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;

public class Demo {

    // 実際のエンドポイントに置き換えてください。
    private static String endpoint = "https://oss-cn-guangzhou.aliyuncs.com";
    // バケット名に置き換えてください。
    private static String bucketName = "examplebucket";

    public static void main(String[] args) throws com.aliyuncs.exceptions.ClientException {
        // 認証情報は OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET から読み込まれます。
        EnvironmentVariableCredentialsProvider credentialsProvider =
            CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        String region = "cn-guangzhou";

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            ossClient.openMetaQuery(bucketName);
        } catch (OSSException oe) {
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:"    + oe.getErrorCode());
            System.out.println("Request ID:"    + oe.getRequestId());
            System.out.println("Host ID:"       + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Error Message: " + ce.getMessage());
        } finally {
            ossClient.shutdown();
        }
    }
}

Python

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 認証情報は OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET から読み込まれます。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

endpoint = "https://oss-cn-guangzhou.aliyuncs.com"
region = "cn-guangzhou"  # V4 署名には必須です。

bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)

bucket.open_bucket_meta_query()

Go

package main

import (
    "context"
    "flag"
    "log"

    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
    region     string
    bucketName string
)

func init() {
    flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}

func main() {
    flag.Parse()

    if len(bucketName) == 0 {
        flag.PrintDefaults()
        log.Fatalf("invalid parameters, bucket name required")
    }
    if len(region) == 0 {
        flag.PrintDefaults()
        log.Fatalf("invalid parameters, region required")
    }

    // 認証情報は OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET から読み込まれます。
    cfg := oss.LoadDefaultConfig().
        WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
        WithRegion(region)

    client := oss.NewClient(cfg)

    request := &oss.OpenMetaQueryRequest{
        Bucket: oss.Ptr(bucketName),
    }
    result, err := client.OpenMetaQuery(context.TODO(), request)
    if err != nil {
        log.Fatalf("failed to open meta query %v", err)
    }

    log.Printf("open meta query result:%#v\n", result)
}

手順 2:オブジェクトの検索と統計情報の収集

本チュートリアルのクエリでは、以下の 3 つの条件すべてに合致するオブジェクトを検索します。

フィールド条件
ファイル名曖昧一致a/b
OSSStorageClass等価Standard
ObjectACL等価private

結果は最終更新日時を基準に降順で並べ替えられます。また、以下の 3 つの集約が計算されます:合計サイズ(sum)、平均サイズ(average)、オブジェクト数(ストレージクラスごとのグループカウント)。

OSS コンソールを使用する

  1. 左側ナビゲーションツリーで、オブジェクト管理データインデックス を選択します。

  2. ストレージクラス標準 に、ACL非公開 に設定します。

  3. オブジェクト名 パラメーターで、ドロップダウンリストから 曖昧一致 を選択し、`a/b` を入力します。

  4. オブジェクト並べ替え順序降順 に設定し、並べ替え基準 のドロップダウンリストから 最終更新日時 を選択します。

  5. データ集約 セクションで、以下の項目を追加します。

    • 出力:オブジェクトサイズ、集約方法:合計 — 合計サイズを計算します。

    • 出力:オブジェクトサイズ、集約方法:平均 — 平均サイズを計算します。

    • 出力:ストレージクラス、集約方法:グループカウント — ストレージクラスごとのオブジェクト数をカウントします。

  6. 今すぐクエリ実行 をクリックします。

OSS SDK を使用する

以下のすべての例では、同一の JSON クエリ式、並べ替えフィールド(`FileModifiedTime`)、並べ替え順序(`desc`)、および集約定義を用いて `DoMetaQuery` を呼び出します。

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

import java.util.ArrayList;
import java.util.List;

public class Demo {

    private static String endpoint   = "https://oss-cn-guangzhou.aliyuncs.com";
    private static String bucketName = "examplebucket";

    public static void main(String[] args) throws Exception {

        EnvironmentVariableCredentialsProvider credentialsProvider =
            CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        String region = "cn-guangzhou";

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            int maxResults = 20;

            // クエリ:プレフィックス a/b、ストレージクラス Standard、ACL private のオブジェクト。
            String query = "{"
                + "\"Operation\":\"and\","
                + "\"SubQueries\":["
                + "  {\"Field\":\"Filename\",\"Value\":\"a/b\",\"Operation\":\"match\"},"
                + "  {\"Field\":\"OSSStorageClass\",\"Value\":\"Standard\",\"Operation\":\"eq\"},"
                + "  {\"Field\":\"ObjectACL\",\"Value\":\"private\",\"Operation\":\"eq\"}"
                + "]}";

            String sort = "FileModifiedTime";

            // 集約:合計サイズ、オブジェクト数、平均サイズ。
            Aggregation aggSum = new Aggregation();
            aggSum.setField("Size");
            aggSum.setOperation("sum");

            Aggregation aggCount = new Aggregation();
            aggCount.setField("Size");
            aggCount.setOperation("count");

            Aggregation aggAvg = new Aggregation();
            aggAvg.setField("Size");
            aggAvg.setOperation("average");

            Aggregations aggregations = new Aggregations();
            List<Aggregation> aggregationList = new ArrayList<>();
            aggregationList.add(aggSum);
            aggregationList.add(aggCount);
            aggregationList.add(aggAvg);
            aggregations.setAggregation(aggregationList);

            DoMetaQueryRequest doMetaQueryRequest =
                new DoMetaQueryRequest(bucketName, maxResults, query, sort);
            doMetaQueryRequest.setAggregations(aggregations);
            doMetaQueryRequest.setOrder(SortOrder.DESC);

            DoMetaQueryResult doMetaQueryResult = ossClient.doMetaQuery(doMetaQueryRequest);

            // 対応するオブジェクトがあれば表示します。
            if (doMetaQueryResult.getFiles() != null) {
                for (ObjectFile file : doMetaQueryResult.getFiles().getFile()) {
                    System.out.println("Filename: "      + file.getFilename());
                    System.out.println("ETag: "          + file.getETag());
                    System.out.println("ObjectACL: "     + file.getObjectACL());
                    System.out.println("OssObjectType: " + file.getOssObjectType());
                    System.out.println("OssStorageClass: " + file.getOssStorageClass());
                    System.out.println("TaggingCount: "  + file.getOssTaggingCount());
                    if (file.getOssTagging() != null) {
                        for (Tagging tag : file.getOssTagging().getTagging()) {
                            System.out.println("Key: "   + tag.getKey());
                            System.out.println("Value: " + tag.getValue());
                        }
                    }
                    if (file.getOssUserMeta() != null) {
                        for (UserMeta meta : file.getOssUserMeta().getUserMeta()) {
                            System.out.println("Key: "   + meta.getKey());
                            System.out.println("Value: " + meta.getValue());
                        }
                    }
                }
            }

            // 集約結果を表示します。
            if (doMetaQueryResult.getAggregations() != null) {
                for (Aggregation aggre : doMetaQueryResult.getAggregations().getAggregation()) {
                    System.out.println("Field: "     + aggre.getField());
                    System.out.println("Operation: " + aggre.getOperation());
                    System.out.println("Value: "     + aggre.getValue());
                    if (aggre.getGroups() != null && aggre.getGroups().getGroup().size() > 0) {
                        System.out.println("Groups value: " + aggre.getGroups().getGroup().get(0).getValue());
                        System.out.println("Groups count: " + aggre.getGroups().getGroup().get(0).getCount());
                    }
                }
            } else {
                System.out.println("NextToken: " + doMetaQueryResult.getNextToken());
            }

        } catch (OSSException oe) {
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:"    + oe.getErrorCode());
            System.out.println("Request ID:"    + oe.getRequestId());
            System.out.println("Host ID:"       + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Error Message: " + ce.getMessage());
        } finally {
            ossClient.shutdown();
        }
    }
}

Python

# -*- coding: utf-8 -*-
import oss2
import json
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import MetaQuery, AggregationsRequest

# 認証情報は OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET から読み込まれます。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

endpoint = "https://oss-cn-guangzhou.aliyuncs.com"
region = "cn-guangzhou"  # V4 署名には必須です。

bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)

# クエリ:プレフィックス a/b、ストレージクラス Standard、ACL private のオブジェクト。
query = {
    "Operation": "and",
    "SubQueries": [
        {"Field": "Filename",       "Value": "a/b",      "Operation": "match"},
        {"Field": "OSSStorageClass","Value": "Standard", "Operation": "eq"},
        {"Field": "ObjectACL",      "Value": "private",  "Operation": "eq"},
    ]
}
query_json = json.dumps(query)

# 集約:合計サイズ、オブジェクト数、平均サイズ。
aggregations = [
    AggregationsRequest(field="Size", operation="sum"),
    AggregationsRequest(field="Size", operation="count"),
    AggregationsRequest(field="Size", operation="average"),
]

do_meta_query_request = MetaQuery(
    max_results=20,
    query=query_json,
    sort="FileModifiedTime",
    order="desc",
    aggregations=aggregations,
)

result = bucket.do_bucket_meta_query(do_meta_query_request)

# 対応するオブジェクトがあれば表示します。
if result.files:
    for file in result.files:
        print(f"Filename: {file.file_name}")
        print(f"ETag: {file.etag}")
        print(f"ObjectACL: {file.object_acl}")
        print(f"OssObjectType: {file.oss_object_type}")
        print(f"TaggingCount: {file.oss_tagging_count}")
        if file.oss_tagging:
            for tag in file.oss_tagging:
                print(f"Key: {tag.key}")
                print(f"Value: {tag.value}")
        if file.oss_user_meta:
            for meta in file.oss_user_meta:
                print(f"Key: {meta.key}")
                print(f"Value: {meta.value}")

# 集約結果を表示します。
if result.aggregations:
    for aggre in result.aggregations:
        print(f"Field: {aggre.field}")
        print(f"Operation: {aggre.operation}")
        print(f"Value: {aggre.value}")

Go

package main

import (
    "context"
    "encoding/json"
    "flag"
    "fmt"
    "log"

    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
    region     string
    bucketName string
)

func init() {
    flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}

func main() {
    flag.Parse()

    if len(bucketName) == 0 {
        flag.PrintDefaults()
        log.Fatalf("invalid parameters, bucket name required")
    }
    if len(region) == 0 {
        flag.PrintDefaults()
        log.Fatalf("invalid parameters, region required")
    }

    // 認証情報は OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET から読み込まれます。
    cfg := oss.LoadDefaultConfig().
        WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
        WithRegion(region)

    client := oss.NewClient(cfg)

    // クエリ:プレフィックス a/b、ストレージクラス Standard、ACL private のオブジェクト。
    query := map[string]interface{}{
        "Operation": "and",
        "SubQueries": []map[string]interface{}{
            {"Field": "Filename",        "Value": "a/b",      "Operation": "match"},
            {"Field": "OSSStorageClass", "Value": "Standard", "Operation": "eq"},
            {"Field": "ObjectACL",       "Value": "private",  "Operation": "eq"},
        },
    }
    queryJSON, err := json.Marshal(query)
    if err != nil {
        log.Fatalf("failed to marshal query %v", err)
    }

    // 集約:合計サイズ、オブジェクト数、平均サイズ。
    aggregations := []oss.MetaQueryAggregation{
        {Field: oss.Ptr("Size"), Operation: oss.Ptr("sum")},
        {Field: oss.Ptr("Size"), Operation: oss.Ptr("count")},
        {Field: oss.Ptr("Size"), Operation: oss.Ptr("average")},
    }

    request := &oss.DoMetaQueryRequest{
        Bucket: oss.Ptr(bucketName),
        MetaQuery: &oss.MetaQuery{
            MaxResults: oss.Ptr(int64(20)),
            Query:      oss.Ptr(string(queryJSON)),
            Sort:       oss.Ptr("FileModifiedTime"),
            Order:      oss.MetaQueryOrderDesc,
            Aggregations: &oss.MetaQueryAggregations{
                Aggregations: aggregations,
            },
        },
    }

    result, err := client.DoMetaQuery(context.TODO(), request)
    if err != nil {
        log.Fatalf("failed to do meta query %v", err)
    }

    fmt.Printf("NextToken: %s\n", *result.NextToken)

    // 対応するオブジェクトを表示します。
    for _, file := range result.Files {
        fmt.Printf("File name: %s\n",         *file.Filename)
        fmt.Printf("Size: %d\n",               file.Size)
        fmt.Printf("File modified time: %s\n", *file.FileModifiedTime)
        fmt.Printf("Oss object type: %s\n",    *file.OSSObjectType)
        fmt.Printf("Oss storage class: %s\n",  *file.OSSStorageClass)
        fmt.Printf("Object ACL: %s\n",         *file.ObjectACL)
        fmt.Printf("ETag: %s\n",               *file.ETag)
        fmt.Printf("Oss CRC64: %s\n",          *file.OSSCRC64)
        if file.OSSTaggingCount != nil {
            fmt.Printf("Oss tagging count: %d\n", *file.OSSTaggingCount)
        }
        for _, tagging := range file.OSSTagging {
            fmt.Printf("Oss tagging key: %s\n",   *tagging.Key)
            fmt.Printf("Oss tagging value: %s\n", *tagging.Value)
        }
        for _, userMeta := range file.OSSUserMeta {
            fmt.Printf("Oss user meta key: %s\n",   *userMeta.Key)
            fmt.Printf("Oss user meta value: %s\n", *userMeta.Value)
        }
    }

    // 集約結果を表示します。
    for _, aggregation := range result.Aggregations {
        fmt.Printf("Aggregation field: %s\n",     *aggregation.Field)
        fmt.Printf("Aggregation operation: %s\n", *aggregation.Operation)
        fmt.Printf("Aggregation value: %f\n",     *aggregation.Value)
    }
}

結果の確認

クエリは、条件に合致する標準ストレージのオブジェクトを 100 個返却します。集約出力の内容は以下のとおりです。

集約出力フィールド
合計サイズ(sum)19.53 MBField: Size / Operation: sum / Value: <bytes>
オブジェクトあたりの平均サイズ約 200 KBField: Size / Operation: average / Value: <bytes>
オブジェクト数(グループカウント)100Groups count: 100

コンソール: クエリ結果 ページに、これらの統計情報が直接表示されます。

SDK: 集約出力ブロック内で、各結果行を上記の表と照合します。sum のエントリはバイト単位の合計サイズを示し、average はバイト単位の平均サイズを示し、グループカウントのエントリは条件に合致するオブジェクト数を示します。

Query results showing total size, average size, and object count

クエリ可能なフィールドのリファレンス

DoMetaQuery を使用してカスタムクエリを作成する際に利用できるフィールドの一覧です。複数のフィールドを組み合わせる場合は、最上位レベルで `"Operation": "and"` または `"Operation": "or"` を使用します。

フィールドサポートされる演算子例の値
Filename文字列match(曖昧一致)、eq(完全一致)a/b
OSSStorageClass文字列eqStandardIAArchive
ObjectACL文字列eqprivatepublic-read
Size整数eqgtgteltlte1048576
FileModifiedTimeタイムスタンプeqgtgteltlte2024-01-01T00:00:00Z

サポートされるフィールド、演算子、および集約タイプの完全な一覧については、「DoMetaQuery」をご参照ください。

次のステップ

  • 追加のクエリ可能フィールド(`Size`、`FileModifiedTime`、またはオブジェクトタグなど)を用いたカスタムクエリを作成するには、`DoMetaQuery` API を直接呼び出します。サポートされるフィールドおよび演算子の完全な一覧については、「DoMetaQuery」をご参照ください。

  • リクエストを手動で署名する必要がある場合は、「(推奨) V4 署名を含める」をご参照ください。