通過OSS資料索引,您可以高效統計海量檔案的數量、大小等資訊,相較傳統的ListObjects介面統計方式,顯著提升統計效率,簡化操作流程,適用於大規模資料統計情境。
方案優勢
A企業在華南3(廣州)地區名為mybucket的儲存空間(Bucket)中,儲存了2億個按業務首碼分類的檔案,共計180萬個目錄。使用OSS資料索引後,檔案統計時間可減少83%。
傳統方式 | OSS資料索引 | |
耗時 | 每日統計花費 2 小時 | 每日統計花費 20 分鐘 |
複雜度 | 對於檔案數量大於1000的目錄,需要多次調用ListObject介面。 | 每個目錄只需調用一次DoMetaQuery介面。 |
方案概覽
使用OSS資料索引進行大規模資料統計的過程如下:
要實現以上過程,您只需要:
開啟資料索引:OSS會幫您自動建立索引表,包含OSS中繼資料、自訂中繼資料和對象標籤。
發起檢索和統計:您需要設定檢索條件,然後調用DoMetaQuery介面,OSS會進行快速檢索。
最後,OSS會返回符合條件檔案的數量、總大小和平均檔案大小等統計資訊,供您分析使用。
快速體驗
步驟一:開啟OSS資料索引
使用OSS控制台
登入OSS管理主控台。
單擊Bucket 列表,然後單擊目標Bucket名稱。
在左側導覽列, 選擇。
在資料索引頁面,單擊立即開啟。
選擇標量檢索,單擊確認開啟。

使用阿里雲SDK
僅Java SDK、Python SDK以及Go SDK支援通過標量檢索功能查詢滿足指定條件的Object。
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 {
// Endpoint以華南3(廣州)為例,其它Region請按實際情況填寫。
private static String endpoint = "https://oss-cn-guangzhou.aliyuncs.com";
// 填寫Bucket名稱,例如examplebucket。
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();
// 填寫Bucket所在地區。以華南3(廣州)為例,Region填寫為cn-guangzhou。
String region = "cn-guangzhou";
// 建立OSSClient執行個體。
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。
ossClient.shutdown();
}
}
}
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填寫Bucket所在地區對應的Endpoint。以華南3(廣州)為例,Endpoint填寫為https://oss-cn-guangzhou.aliyuncs.com。
endpoint = "https://oss-cn-guangzhou.aliyuncs.com"
# 填寫Endpoint對應的Region資訊,例如cn-guangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-guangzhou"
# examplebucket填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)
# 開啟資料索引功能。
bucket.open_bucket_meta_query()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 // 定義一個變數來儲存從命令列擷取的地區(Region)資訊
bucketName string // 定義一個變數來儲存從命令列擷取的儲存空間名稱
)
// init函數在main函數之前執行,用來初始化程式
func init() {
// 設定命令列參數來指定region
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
// 設定命令列參數來指定bucket名稱
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") // 記錄錯誤並終止程式
}
// 建立用戶端配置,並使用環境變數作為憑證提供者
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg) // 使用配置建立一個新的OSS用戶端執行個體
// 構建一個OpenMetaQuery請求,用於開啟特定儲存空間的中繼資料查詢功能
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) // 列印開啟中繼資料查詢的結果
}步驟二:發起檢索和統計
使用OSS控制台
檢索條件設定
在左側導覽列, 選擇。
儲存類型選擇標準儲存,讀寫權限選擇私人。
通過模糊比對目錄首碼“a/b”來指定目錄。

結果輸出設定
按對象的最後修改時間降序排序結果。
對篩選後檔案大小進行求和及平均值的計算。
按儲存類型進行分組計數,以統計檔案數量。

單擊立即查詢。
使用阿里雲SDK
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 {
// Endpoint以華南3(廣州)為例,其它Region請按實際情況填寫。
private static String endpoint = "https://oss-cn-guangzhou.aliyuncs.com";
// 填寫Bucket名稱,例如examplebucket。
private static String bucketName = "examplebucket";
public static void main(String[] args) throws Exception {
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填寫Bucket所在地區。以華南3(廣州)為例,Region填寫為cn-guangzhou。
String region = "cn-guangzhou";
// 建立OSSClient執行個體。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// 設定查詢參數,指定返迴文件的最大數量(20個)
int maxResults = 20;
// 設定查詢條件:檔案名稱包含"a/b",且檔案儲存體類型為"Standard",存取權限為"private"
// 查詢語句使用邏輯運算子"and"來串連多個子查詢條件
String query = "{\n" +
" \"Operation\": \"and\",\n" +
" \"SubQueries\": [\n" +
" {\n" +
" \"Field\": \"Filename\",\n" +
" \"Value\": \"a/b\",\n" +
" \"Operation\": \"match\"\n" +
" },\n" +
" {\n" +
" \"Field\": \"OSSStorageClass\",\n" +
" \"Value\": \"Standard\",\n" +
" \"Operation\": \"eq\"\n" +
" },\n" +
" {\n" +
" \"Field\": \"ObjectACL\",\n" +
" \"Value\": \"private\",\n" +
" \"Operation\": \"eq\"\n" +
" }\n" +
" ]\n" +
"}";
String sort = "FileModifiedTime";// 設定按檔案修改時間排序
// 建立彙總操作執行個體,用於統計檔案的大小(Size)的總和、數量和平均值
Aggregation aggregationRequest1 = new Aggregation();
aggregationRequest1.setField("Size");// 設定彙總欄位為檔案大小
aggregationRequest1.setOperation("sum");// 計算檔案大小的總和
Aggregation aggregationRequest2 = new Aggregation();
aggregationRequest2.setField("Size");// 設定彙總欄位為檔案大小
aggregationRequest2.setOperation("count");// 計算檔案數量
Aggregation aggregationRequest3 = new Aggregation();
aggregationRequest3.setField("Size");// 設定彙總欄位為檔案大小
aggregationRequest3.setOperation("average");// 計算檔案大小的平均值
// 將所有彙總請求添加到一個列表中
Aggregations aggregations = new Aggregations();
List<Aggregation> aggregationList = new ArrayList<>();
aggregationList.add(aggregationRequest1);// 添加求和彙總
aggregationList.add(aggregationRequest2);// 添加計數彙總
aggregationList.add(aggregationRequest3);// 添加平均值彙總
aggregations.setAggregation(aggregationList);// 將所有彙總操作設定到Aggregations對象中
// 建立DoMetaQueryRequest請求對象,傳入Bucket名稱、最大返迴文件數、查詢條件和定序
DoMetaQueryRequest doMetaQueryRequest = new DoMetaQueryRequest(bucketName, maxResults, query, sort);
// 將彙總操作添加到Meta查詢請求中
doMetaQueryRequest.setAggregations(aggregations);
// 設定排序方式為降序(DESC)
doMetaQueryRequest.setOrder(SortOrder.DESC);
// 執行Meta查詢請求,擷取查詢結果
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());// 檔案ETag
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());
}
}
}
} else 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) {
// 捕獲OSS異常並輸出相關資訊
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執行個體
ossClient.shutdown();
}
}
}# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import MetaQuery, AggregationsRequest
import json
# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填寫Bucket所在地區對應的Endpoint。以華南3(廣州)為例,Endpoint填寫為https://oss-cn-guangzhou.aliyuncs.com。
endpoint = "https://oss-cn-guangzhou.aliyuncs.com"
# 填寫Endpoint對應的Region資訊,例如cn-guangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-guangzhou"
# 填寫儲存空間名稱,以examplebucket為例。
bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)
# 查詢條件:檔案名稱包含"a/b",且檔案儲存體類型為"Standard",存取權限為"private"
query = {
"Operation": "and",
"SubQueries": [
{"Field": "Filename", "Value": "a/b", "Operation": "match"},
{"Field": "OSSStorageClass", "Value": "Standard", "Operation": "eq"},
{"Field": "ObjectACL", "Value": "private", "Operation": "eq"}
]
}
# 將字典轉換為JSON字串
query_json = json.dumps(query)
# 建立彙總操作執行個體,用於統計檔案的大小(Size)的總和、數量和平均值
aggregations = [
AggregationsRequest(field="Size", operation="sum"), # 計算檔案大小的總和
AggregationsRequest(field="Size", operation="count"), # 計算檔案的數量
AggregationsRequest(field="Size", operation="average") # 計算檔案大小的平均值
]
# 建立MetaQuery請求對象,指定查詢條件、最大返迴文件數、排序欄位和方式以及彙總操作
do_meta_query_request = MetaQuery(
max_results=20, # 返回最多20個檔案
query=query_json, # 設定查詢條件
sort="FileModifiedTime", # 按檔案修改時間排序
order="desc", # 降序排序
aggregations=aggregations # 設定彙總操作
)
# 執行Meta查詢請求,擷取查詢結果
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}") # 列印檔案的ETag
print(f"ObjectACL: {file.object_acl}") # 列印檔案的存取控制清單(ACL)
print(f"OssObjectType: {file.oss_object_type}") # 列印檔案的OSS物件類型
print(f"OssStorageClass: {file.oss_storage_class}") # 列印檔案的儲存類型
print(f"TaggingCount: {file.oss_tagging_count}") # 列印檔案的標籤數量
# 列印檔案的所有標籤
if file.oss_tagging:
for tag in file.oss_tagging:
print(f"Key: {tag.key}") # 列印標籤的Key
print(f"Value: {tag.value}") # 列印標籤的Value
# 列印檔案的使用者中繼資料
if file.oss_user_meta:
for meta in file.oss_user_meta:
print(f"Key: {meta.key}") # 列印使用者中繼資料的Key
print(f"Value: {meta.value}") # 列印使用者中繼資料的Value
# 列印彙總結果
if result.aggregations:
for aggre in result.aggregations:
print(f"Field: {aggre.field}") # 列印彙總操作欄位
print(f"Operation: {aggre.operation}") # 列印彙總操作類型(如sum、count、average)
print(f"Value: {aggre.value}") # 列印彙總結果值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 // 定義一個變數來儲存從命令列擷取的地區(Region)資訊
bucketName string // 定義一個變數來儲存從命令列擷取的儲存空間名稱
)
// init函數在main函數之前執行,用來初始化程式
func init() {
// 設定命令列參數來指定region,預設為空白字串
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
// 設定命令列參數來指定bucket名稱,預設為空白字串
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")
}
// 建立用戶端配置,並使用環境變數作為憑證提供者和指定的地區
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg) // 使用配置建立一個新的OSS用戶端執行個體
// 構建查詢條件,檔案名稱包含"a/b",儲存類型為"Standard",存取權限為"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"},
},
}
// 將查詢條件轉為JSON字串
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")}, // 計算檔案大小平均值
}
// 構建一個DoMetaQuery請求,用於執行中繼資料查詢
request := &oss.DoMetaQueryRequest{
Bucket: oss.Ptr(bucketName), // 指定要查詢的儲存空間名稱
MetaQuery: &oss.MetaQuery{
MaxResults: oss.Ptr(int64(20)), // 最大返回結果數:20個結果
Query: oss.Ptr(string(queryJSON)), // 查詢條件:大小大於1MB的對象
Sort: oss.Ptr("Size"), // 排序欄位:按對象大小排序
Order: oss.MetaQueryOrderAsc, // 排序次序:升序
Aggregations: &oss.MetaQueryAggregations{
Aggregations: aggregations}, // 彙總操作:計算檔案大小的總和、數量和平均值
},
}
result, err := client.DoMetaQuery(context.TODO(), request) // 發送請求以執行中繼資料查詢
if err != nil {
log.Fatalf("failed to do meta query %v", err)
}
// 列印NextToken,用於分頁查詢下一頁的資料
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 Key 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)
}
}
步驟三:結果驗證
使用OSS控制台
如圖所示,合格100個標準儲存類型檔案總大小為19.53MB,平均每個檔案約200KB。

使用阿里雲SDK
如圖所示,合格100個標準儲存類型檔案總大小為19.53MB,平均每個檔案約200KB。

瞭解更多
如果您的程式自訂要求較高,您可以直接發起REST API請求。直接發起REST API請求需要手動編寫代碼計算簽名。更多資訊,請參見簽名版本4和DoMetaQuery API。