本報告提供了PolarDB PostgreSQL版在多種典型工作負載下的效能基準測試結果。測試基於業界標準的 YCSB(Yahoo! Cloud Serving Benchmark)工具進行,旨在為您的技術選型、應用設計和容量規劃提供量化的資料參考。測試結果表明,該功能在各種資料規模下均能提供穩定且高效能的讀寫服務。尤其在單點查詢(Point Lookup)情境下表現優異,峰值 OPS(每秒運算元)可達 983,524(64 核 256 GB 規格,10 GB 資料量下的 100% 讀取情境)。
測試方法與環境
測試環境配置
組件 | 規格與配置 |
測試叢集(PolarDB) |
|
壓測用戶端(ECS) |
|
基準測試載入器
效能指標:OPS (Operations Per Second),即資料庫每秒處理的運算元。
工作負載模型
通過配置YCSB的CoreWorkload來類比五種典型的業務情境。測試資料模型為單表usertable,主鍵類型HASH,欄位包含10個100 位元組的隨機字串(每個記錄約1 KB)。
YCSB Workload | 情境描述 | 核心參數配置 |
| 100%寫入 |
|
| 100%更新 |
|
| 100%單點查詢 |
|
| 50%讀+50%更新 |
|
| 100%範圍查詢 |
|
其他壓測方式
壓測方式 | 說明 |
資料量 | 分別預先載入1 M / 10 M / 100 M / 1 B條記錄後進行壓測(對應約1 GB / 10 GB / 100 GB / 1 TB資料)。 |
壓測時間長度 | 每輪5分鐘(maxexecutiontime=300s) |
取值方式 | 不同壓測並發線程下的最佳輸送量。 |
分規格詳細測試結果
以下三組資料分別展示 8 核 32 GB、32 核 128 GB、64 核 256 GB 三種叢集規格下,不同資料規模與不同工作負載的輸送量(OPS)。取不同壓測並發線程下的最佳輸送量。
8 核 32 GB 規格
測試情境 | 1 GB 資料量(OPS) | 10 GB 資料量(OPS) | 100 GB 資料量(OPS) | 1 TB 資料量(OPS) |
100% 讀取(Read) | 243,067 | 238,188 | 140,199 | 116,189 |
100% 範圍掃描(Scan) | 37,142 | 36,945 | 5,626 | 4,857 |
50% 讀 + 50% 更新 | 89,119 | 84,636 | 65,903 | 57,164 |
100% 更新(Update) | 45,401 | 42,869 | 34,741 | 29,907 |
100% 寫入(Insert) | 57,806 | 46,621 | 44,428 | 44,359 |
32 核 128 GB 規格
測試情境 | 1 GB 資料量(OPS) | 10 GB 資料量(OPS) | 100 GB 資料量(OPS) | 1 TB 資料量(OPS) |
100% 讀取(Read) | 578,397 | 575,689 | 462,904 | 373,101 |
100% 範圍掃描(Scan) | 90,256 | 89,789 | 25,986 | 10,278 |
50% 讀 + 50% 更新 | 221,826 | 216,588 | 164,912 | 120,688 |
100% 更新(Update) | 114,770 | 114,696 | 92,479 | 78,317 |
100% 寫入(Insert) | 128,332 | 121,148 | 117,396 | 112,275 |
64 核 256 GB 規格
測試情境 | 1 GB 資料量(OPS) | 10 GB 資料量(OPS) | 100 GB 資料量(OPS) | 1 TB 資料量(OPS) |
100% 讀取(Read) | 894,926 | 983,524 | 980,197 | 653,825 |
100% 範圍掃描(Scan) | 138,609 | 142,560 | 140,653 | 14,171 |
50% 讀 + 50% 更新 | 318,094 | 312,043 | 288,028 | 189,536 |
100% 更新(Update) | 171,349 | 170,789 | 154,085 | 115,961 |
100% 寫入(Insert) | 171,682 | 176,069 | 167,877 | 165,308 |
附錄:測試步驟
本附錄提供了複現上述效能測試所需的詳細步驟,供需要進行二次驗證或定製化的測試參考。
1. 配置YCSB
在運行測試前,需要對YCSB的DynamoDB用戶端進行配置。
配置身份憑證
編輯
dynamodb/conf/AWSCredentials.properties檔案,填入您在PolarDB控制台建立的DynamoDB專用帳號資訊。# 帳號名即為AccessKey ID accessKey = <YOUR_ACCESS_KEY_ID> # 密鑰 secretKey = <YOUR_SECRET_ACCESS_KEY>配置串連屬性
編輯
dynamodb/conf/dynamodb.properties檔案,指定要串連的PolarDB叢集串連資訊。# 認證檔案的絕對路徑 dynamodb.awsCredentialsFile = /path/to/your/AWSCredentials.properties # 您需要提前在叢集中建立一個usertable表。此處建立僅有分區鍵的usertable表,分區鍵名為pk。 dynamodb.primaryKey = pk # PolarDB的DynamoDB訪問地址,必須包含http://首碼 dynamodb.endpoint = http://<your-polardb-ddb-endpoint>:<port> # region參數必須設定為空白 dynamodb.region = # 測試所用的表主鍵名和類型,需與測試表保持一致 dynamodb.primaryKey = HASH
2. 適配YCSB的Update操作
YCSB官方的DynamoDB用戶端預設使用已廢棄的AttributeUpdates參數執行更新。為相容PolarDB所支援的新版UpdateExpression參數,您需要修改YCSB源碼。
檔案路徑:
dynamodb/src/main/java/site/ycsb/db/DynamoDBClient.java修改方法:
update()
修改前(原始代碼)
@Override
public Status update(String table, String key, Map<String, ByteIterator> values) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("updatekey: " + key + " from table: " + table);
}
Map<String, AttributeValueUpdate> attributes = new HashMap<>(values.size());
for (Entry<String, ByteIterator> val : values.entrySet()) {
AttributeValue v = new AttributeValue(val.getValue().toString());
attributes.put(val.getKey(), new AttributeValueUpdate().withValue(v).withAction("PUT"));
}
UpdateItemRequest req = new UpdateItemRequest(table, createPrimaryKey(key), attributes);
try {
dynamoDB.updateItem(req);
} catch (AmazonServiceException ex) {
LOGGER.error(ex);
return Status.ERROR;
} catch (AmazonClientException ex) {
LOGGER.error(ex);
return CLIENT_ERROR;
}
return Status.OK;
}修改後(使用UpdateExpression)
@Override
public Status update(String table, String key, Map<String, ByteIterator> values) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("updatekey: " + key + " from table: " + table);
}
StringBuilder updateExp = new StringBuilder("SET ");
Map<String, String> attrNames = new HashMap<>();
Map<String, AttributeValue> attrValues = new HashMap<>();
boolean first = true;
for (Map.Entry<String, ByteIterator> entry : values.entrySet()) {
String attr = entry.getKey();
if (!first) {
updateExp.append(", ");
}
String attrName = "#" + attr;
String valueName = ":" + attr;
updateExp.append(attrName).append(" = ").append(valueName);
attrNames.put(attrName, attr);
attrValues.put(valueName, new AttributeValue(entry.getValue().toString()));
first = false;
}
UpdateItemRequest req = new UpdateItemRequest()
.withTableName(table)
.withKey(createPrimaryKey(key))
.withUpdateExpression(updateExp.toString())
.withExpressionAttributeNames(attrNames)
.withExpressionAttributeValues(attrValues);
try {
dynamoDB.updateItem(req);
} catch (AmazonServiceException ex) {
LOGGER.error(ex);
return Status.ERROR;
} catch (AmazonClientException ex) {
LOGGER.error(ex);
return CLIENT_ERROR;
}
return Status.OK;
}3. 執行測試
測試分為load(載入初始資料)和run(運行工作負載)兩個階段。以1 GB資料量(100萬條記錄)、128並發線程、唯讀模型為例:
在其他資料量情境下,請修改命令中的recordcount和operationcount參數。
載入資料(Load Phase)
# 解釋: # -s: 顯示狀態更新 # -P workloads/workload_read_only: 指定基礎workload檔案 # -P /path/to/dynamodb.properties: 指定資料庫連接設定檔 # -p recordcount=1000000: 定義總記錄數 # -p operationcount=1000000: 定義本次運行要執行的操作總數 # -threads 128: 指定並發線程數 nohup ./bin/ycsb load dynamodb -s \ -P workloads/workload_read_only \ -P /path/to/dynamodb.properties \ -p recordcount=1000000 \ -p operationcount=1000000 \ -threads 128 \ > load.log 2>&1 &運行測試(Run Phase)
nohup ./bin/ycsb run dynamodb -s \ -P workloads/workload_read_only \ -P /path/to/dynamodb.properties \ -p recordcount=1000000 \ -p operationcount=1000000 \ -threads 128 \ > run.log 2>&1 &