通過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 (
"fmt"
"os"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 建立OSSClient執行個體。
// yourRegion填寫Bucket所在地區,以華南3(廣州)為例,填寫為cn-guangzhou。其它Region請按實際情況填寫。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// 設定簽名版本為V4(推薦版本)。
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
// yourEndpoint填寫Bucket對應的Endpoint,以華南3(廣州)為例,填寫為https://oss-cn-guangzhou.aliyuncs.com。其它Region請按實際情況填寫。
client, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
//開啟資料索引功能。
//填寫需要開啟資料索引的bucket名稱,以examplebucket為例。
err = client.OpenMetaQuery("examplebucket")
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
fmt.Println("Open data query success")
}
步驟二:發起檢索和統計
使用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 (
"encoding/json" // 匯入 json 包
"fmt"
"os"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
region := "cn-guangzhou" // 設定Region,以華南3(廣州)為例,填寫cn-guangzhou
endpoint := "https://oss-cn-guangzhou.aliyuncs.com" // 設定Bucket對應的Endpoint,以華南3(廣州)為例,填寫https://oss-cn-guangzhou.aliyuncs.com
bucketName := "examplebucket" // 設定Bucket名稱,例如examplebucket
// 建立OSSClient執行個體。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region(region))
// 設定簽名版本V4
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
client, err := oss.New(endpoint, "", "", clientOptions...)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 構建查詢條件,檔案名稱包含"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 {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 建立彙總操作,用於統計檔案大小的總和、數量和平均值
aggregations := []oss.MetaQueryAggregationRequest{
{Field: "Size", Operation: "sum"}, // 計算檔案大小總和
{Field: "Size", Operation: "count"}, // 計算檔案數量
{Field: "Size", Operation: "average"}, // 計算檔案大小平均值
}
// 建立MetaQuery請求對象
metaQueryRequest := oss.MetaQuery{
MaxResults: 20, // 返回最多20個檔案
Query: string(queryJSON), // 設定查詢條件
Sort: "FileModifiedTime", // 按檔案修改時間排序
Order: "desc", // 降序排序
Aggregations: aggregations, // 設定彙總操作
}
// 執行Meta查詢請求,擷取查詢結果
result, err := client.DoMetaQuery(bucketName, metaQueryRequest)
if err != nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// 列印NextToken(用於分頁查詢)
if result.NextToken != "" {
fmt.Printf("NextToken: %s\n", result.NextToken)
}
// 列印查詢結果中滿足條件的檔案資訊
for _, file := range result.Files {
fmt.Printf("Filename: %s\n", file.Filename)
fmt.Printf("ETag: %s\n", file.ETag)
fmt.Printf("ObjectACL: %s\n", file.ObjectACL)
fmt.Printf("OssObjectType: %s\n", file.OssObjectType)
fmt.Printf("OssStorageClass: %s\n", file.OssStorageClass)
fmt.Printf("TaggingCount: %d\n", file.OssTaggingCount)
// 列印檔案標籤資訊
for _, tag := range file.OssTagging {
fmt.Printf("Key: %s\n", tag.Key)
fmt.Printf("Value: %s\n", tag.Value)
}
// 列印使用者中繼資料
for _, meta := range file.OssUserMeta {
fmt.Printf("Key: %s\n", meta.Key)
fmt.Printf("Value: %s\n", meta.Value)
}
}
// 列印彙總結果
for _, aggregation := range result.Aggregations {
fmt.Printf("Field: %s\n", aggregation.Field)
fmt.Printf("Operation: %s\n", aggregation.Operation)
fmt.Printf("Value: %v\n", aggregation.Value)
}
}
步驟三:結果驗證
使用OSS控制台
如圖所示,合格100個標準儲存類型檔案總大小為19.53MB,平均每個檔案約200KB。
使用阿里雲SDK
如圖所示,合格100個標準儲存類型檔案總大小為19.53MB,平均每個檔案約200KB。
瞭解更多
如果您的程式自訂要求較高,您可以直接發起REST API請求。直接發起REST API請求需要手動編寫代碼計算簽名。更多資訊,請參見簽名版本4和DoMetaQuery API。