性能测试报告

更新时间:
复制 MD 格式

本报告提供了PolarDB PostgreSQL在多种典型工作负载下的性能基准测试结果。测试基于业界标准的 YCSB(Yahoo! Cloud Serving Benchmark)工具进行,旨在为您的技术选型、应用设计和容量规划提供量化的数据参考。测试结果表明,该功能在各种数据规模下均能提供稳定且高性能的读写服务。尤其在单点查询(Point Lookup)场景下表现优异,峰值 OPS(每秒操作数)可达 983,524(64 核 256 GB 规格,10 GB 数据量下的 100% 读取场景)。

测试方法与环境

测试环境配置

组件

规格与配置

测试集群(PolarDB

  • 集群数量:1

  • 内核版本:PostgreSQL 16

  • 产品版本:企业版

  • 节点规格:独享规格,一个读写节点一个只读节点,分别测试了 8 核 32 GB、32 核 128 GB、64 核 256 GB 三种配置

压测客户端(ECS)

  • 客户端数量:与测试集群相同VPC下的多台ECS。

  • 依次压测16、32、64、96、128、160、192、256、512、1024线程。

  • 客户端规格:64核 256 GB。

基准测试工具

工作负载模型

通过配置YCSBCoreWorkload来模拟五种典型的业务场景。测试数据模型为单表usertable,主键类型HASH,字段包含10100 字节的随机字符串(每个记录约1 KB)。

YCSB Workload

场景描述

核心参数配置

workload_insert_only

100%写入

insertproportion=1.0

workload_update_only

100%更新

updateproportion=1.0

workload_read_only

100%单点查询

readproportion=1.0

workload_read_update

50%读+50%更新

readproportion=0.5, updateproportion=0.5

workload_scan_only

100%范围查询

scanproportion=1.0

其他压测方式

压测方式

说明

数据量

分别预加载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

在运行测试前,需要对YCSBDynamoDB客户端进行配置。

  1. 配置身份凭证

    编辑dynamodb/conf/AWSCredentials.properties文件,填入您在PolarDB控制台创建的DynamoDB专用账号信息

    # 账号名即为AccessKey ID
    accessKey = <YOUR_ACCESS_KEY_ID>
    
    # 密钥
    secretKey = <YOUR_SECRET_ACCESS_KEY>
  2. 配置连接属性

    编辑dynamodb/conf/dynamodb.properties文件,指定要连接的PolarDB集群连接信息

    # 认证文件的绝对路径
    dynamodb.awsCredentialsFile = /path/to/your/AWSCredentials.properties
    
    # 您需要提前在集群中创建一个usertable表。此处创建仅有分区键的usertable表,分区键名为pk。
    dynamodb.primaryKey = pk
    
    # PolarDBDynamoDB访问地址,必须包含http://前缀
    dynamodb.endpoint = http://<your-polardb-ddb-endpoint>:<port>
    
    # region参数必须设置为空
    dynamodb.region = 
    
    # 测试所用的表主键名和类型,需与测试表保持一致
    dynamodb.primaryKey = HASH

2. 适配YCSBUpdate操作

重要

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并发线程、只读模型为例:

说明

在其他数据量场景下,请修改命令中的recordcountoperationcount参数。

  1. 加载数据(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 &
  2. 运行测试(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 &