OSS データインデックスにより、単一の API 呼び出しで数億個に及ぶオブジェクトに対してクエリ実行および集約統計処理が可能です。従来の `ListObjects` のページネーションによる反復呼び出しは不要です。
本チュートリアルでは、以下の手順を実施します。
コンソールまたは SDK を使用して、バケットでデータインデックスを有効化します。
フィルター(プレフィックス、ストレージクラス、アクセス制御リスト (ACL))および集約操作(合計サイズ、平均サイズ、オブジェクト数)を指定したクエリを実行します。
結果が期待される出力と一致することを確認します。
仕組み
バケットでデータインデックスを有効化すると、OSS はそのバケット内のオブジェクトのメタデータ、ユーザーメタデータ、およびオブジェクトタグに基づいてインデックステーブルを構築します。インデックス作成後は、JSON 形式のクエリ式および集約定義を含む `DoMetaQuery` 操作を呼び出します。OSS はこのクエリをインデックステーブルに対して評価し、対象となるオブジェクトおよび集約統計結果を返却します。この際、バケット内のオブジェクトを 1 つずつスキャンする必要はありません。
パフォーマンス比較(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 コンソールを使用する
OSS コンソール にログインします。
左側ナビゲーションウィンドウで、バケット をクリックします。バケット一覧ページで、データインデックスを有効化するバケット名をクリックします。
左側ナビゲーションツリーで、オブジェクト管理 > データインデックス を選択します。
データインデックス ページで、今すぐ有効化 をクリックします。
データインデックスダイアログボックスで、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(®ion, "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 コンソールを使用する
左側ナビゲーションツリーで、オブジェクト管理 > データインデックス を選択します。
ストレージクラス を 標準 に、ACL を 非公開 に設定します。
オブジェクト名 パラメーターで、ドロップダウンリストから 曖昧一致 を選択し、`
a/b` を入力します。オブジェクト並べ替え順序 を 降順 に設定し、並べ替え基準 のドロップダウンリストから 最終更新日時 を選択します。
データ集約 セクションで、以下の項目を追加します。
出力:オブジェクトサイズ、集約方法:合計 — 合計サイズを計算します。
出力:オブジェクトサイズ、集約方法:平均 — 平均サイズを計算します。
出力:ストレージクラス、集約方法:グループカウント — ストレージクラスごとのオブジェクト数をカウントします。
今すぐクエリ実行 をクリックします。
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(®ion, "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 MB | Field: Size / Operation: sum / Value: <bytes> |
| オブジェクトあたりの平均サイズ | 約 200 KB | Field: Size / Operation: average / Value: <bytes> |
| オブジェクト数(グループカウント) | 100 | Groups count: 100 |
コンソール: クエリ結果 ページに、これらの統計情報が直接表示されます。
SDK: 集約出力ブロック内で、各結果行を上記の表と照合します。sum のエントリはバイト単位の合計サイズを示し、average はバイト単位の平均サイズを示し、グループカウントのエントリは条件に合致するオブジェクト数を示します。

クエリ可能なフィールドのリファレンス
DoMetaQuery を使用してカスタムクエリを作成する際に利用できるフィールドの一覧です。複数のフィールドを組み合わせる場合は、最上位レベルで `"Operation": "and"` または `"Operation": "or"` を使用します。
| フィールド | 型 | サポートされる演算子 | 例の値 |
|---|---|---|---|
Filename | 文字列 | match(曖昧一致)、eq(完全一致) | a/b |
OSSStorageClass | 文字列 | eq | Standard、IA、Archive |
ObjectACL | 文字列 | eq | private、public-read |
Size | 整数 | eq、gt、gte、lt、lte | 1048576 |
FileModifiedTime | タイムスタンプ | eq、gt、gte、lt、lte | 2024-01-01T00:00:00Z |
サポートされるフィールド、演算子、および集約タイプの完全な一覧については、「DoMetaQuery」をご参照ください。
次のステップ
追加のクエリ可能フィールド(`
Size`、`FileModifiedTime`、またはオブジェクトタグなど)を用いたカスタムクエリを作成するには、`DoMetaQuery` API を直接呼び出します。サポートされるフィールドおよび演算子の完全な一覧については、「DoMetaQuery」をご参照ください。リクエストを手動で署名する必要がある場合は、「(推奨) V4 署名を含める」をご参照ください。