All Products
Search
Document Center

Hologres:Stress testing data writes, updates, and point queries

Last Updated:Mar 11, 2026

Hologres is a real-time data warehouse engine compatible with the PostgreSQL protocol. It supports real-time writes, updates, and Online Analytical Processing (OLAP) on petabytes of data, along with high-concurrency, low-latency online data services.

This topic explains how to run performance tests for data writes, updates, and point queries using holo-e2e-performance-tool, and provides reference benchmark results on a 64-vCPU instance.

Test scenarios

Scenario

What is tested

Storage formats

Data write

Write throughput to row-oriented, column-oriented, and row-column hybrid tables

All three

Data update

Update throughput for global and partial updates on tables with a primary key

All three

Point query

Point query performance filtering by primary key

Row-oriented and row-column hybrid only

Column-oriented tables are not suitable for point queries and are excluded from that scenario.

How it works

The three test scenarios build on each other:

  1. Write test -- Populate a table with test data.

  2. Update test -- Reuse the same table to measure update throughput (keep the table from step 1).

  3. Point query test -- Query the same table by primary key.

Write and update mechanics

The tool supports two write modes:

  • Fixed Copy mode -- Uses the PostgreSQL COPY statement, optimized with Fixed Plan for faster SQL execution.

  • Insert mode -- Uses standard INSERT statements, also optimized with Fixed Plan.

In both modes, the tool automatically adds two columns to the table:

Column

Role

Behavior

id

Primary key and distribution key

Starts at 1 and increments with each row

ts

Segment key

Set to the current timestamp on each write

For every configured TEXT column, the tool writes a string of the specified length with the id value appended. The test stops when the target row count or duration is reached.

During updates, the same incrementing id pattern is used. For partial updates, only a subset of TEXT columns is rewritten.

Point query mechanics

The tool supports two query modes:

  • Asynchronous mode -- The point query API is non-blocking. Multiple requests are batched into a single SQL statement, maximizing throughput. Best for high-throughput scenarios such as Flink-based real-time table joins.

  • Synchronous mode -- The point query API is blocking. Each request maps to one SQL statement and completes before the next starts. Best for latency-sensitive scenarios.

During the test, the tool randomly selects a primary key within the configured range and performs a point query. The test stops when the target duration is reached.

Prerequisites

Before you begin, prepare the following:

  • A Hologres instance (dedicated, pay-as-you-go). The benchmark results in this topic use a 64-vCPU, 256 GB memory instance. Use a newly created instance rather than one that has been upgraded or downgraded, to minimize variables that affect results.

  • An Elastic Compute Service (ECS) instance to serve as the test client:

    • Recommended instance type: ecs.g6.4xlarge

    • Operating system: Alibaba Cloud Linux 3.2104 LTS 64-bit

    • Storage: enterprise SSD (ESSD)

    • The ECS instance must be in the same region, Virtual Private Cloud (VPC), and zone as the Hologres instance

  • A database created on the Hologres instance. For details, see Create a database.

  • Java Development Kit (JDK) 11 installed on the ECS instance. For details, see Manually deploy OpenJDK.

  • The holo-e2e-performance-tool JAR file, uploaded to the ECS instance. For upload instructions, see Use Workbench to upload or download files.

The ECS specifications above are recommendations, not requirements. During tests, monitor the ECS CPU and network bandwidth to confirm the client is not a bottleneck.

About the test tool

holo-e2e-performance-tool is an open-source tool developed by the Hologres team. It integrates table creation, test data generation, and performance measurement into a single JAR, so there is no need to prepare test data separately. The primary key for generated data is a series of consecutive integers, which guarantees full hit rates during update and point query tests.

Run a data write test

Step 1: Create the configuration file

On the ECS instance, create a file named test_insert.conf with the following content:

# Connection configuration
holoClient.jdbcUrl=jdbc:hologres://<ENDPOINT>:<PORT>/<DBNAME>
holoClient.username=<AccessKey_ID>
holoClient.password=<AccessKey_Secret>
holoClient.writeThreadSize=100

# Write configuration
put.threadSize=8
put.testByTime=false
put.rowNumber=200000000
put.testTime=600000

# Table configuration
put.tableName=kv_test
put.columnCount=20
put.columnSize=20
put.orientation=row

# Other configurations
put.createTableBeforeRun=true
put.deleteTableAfterDone=false
put.vacuumTableBeforeRun=false
This example creates a row-oriented table. To test a column-oriented or row-column hybrid table, change orientation to column or row,column.

Replace the placeholders with your actual values:

Placeholder

Description

Where to find it

<ENDPOINT>

VPC domain name of the Hologres instance

Instance Details > Network Information in the Hologres console

<PORT>

Port number of the Hologres instance

Same location as above

<DBNAME>

Name of the test database

The database you created in the prerequisites

<AccessKey_ID>

AccessKey ID of your Alibaba Cloud account

AccessKey Management page

<AccessKey_Secret>

AccessKey secret of your Alibaba Cloud account

Same location as above

Configuration parameters

Module

Parameter

Description

Notes

Connection

jdbcUrl

Java Database Connectivity (JDBC) connection string. Format: jdbc:hologres://<ENDPOINT>:<PORT>/<DBNAME>

Use the VPC domain name for <ENDPOINT>.

username

AccessKey ID

password

AccessKey secret

writeThreadSize

Number of write threads per Holo Client. Each thread uses one connection. Applies to Insert mode only.

In Fixed Copy mode, the connection count equals threadSize instead.

Write

threadSize

Number of data generation threads

In Fixed Copy mode, each thread uses one connection (total connections = threadSize). In Insert mode, threads share a single Holo Client (total connections = writeThreadSize). For a 64-vCPU instance in Fixed Copy mode, 8 threads is a good starting point. Increase this if CPU utilization is low.

testByTime

Controls whether the test runs for a fixed duration or a fixed number of rows

true: run for the duration specified in testTime. false: run until the row count specified in rowNumber is reached.

rowNumber

Target row count. Applies only when testByTime is false.

testTime

Target duration in milliseconds. Applies only when testByTime is true.

Table

tableName

Name of the test table

columnCount

Number of TEXT columns in the table

columnSize

Character length of each TEXT column

orientation

Storage format of the table

row, column, or row,column

Other

createTableBeforeRun

Whether to create the table before the test starts

true: drops any existing table with the same name and creates a new one. false: uses the existing table.

deleteTableAfterDone

Whether to delete the table after the test completes

Set to false to retain data for subsequent update or point query tests.

vacuumTableBeforeRun

Whether to run VACUUM (compaction) before the test starts

VACUUM forces compaction. This affects Insert mode only; Fixed Copy mode is unaffected.

Step 2: Run the test

# Fixed Copy mode
java -jar holo-e2e-performance-tool-1.0.0.jar test_insert.conf FIXED_COPY

# Or, Insert mode
java -jar holo-e2e-performance-tool-1.0.0.jar test_insert.conf INSERT

Step 3: View the results

cat result.csv

See Result fields for the output format.

Important

Keep the test table (deleteTableAfterDone=false) if you plan to run update or point query tests next.

Run a data update test

The update test reuses the table populated during the write test. Two update types are supported: global update (all columns) and partial update (a subset of columns).

Global update

  1. Create a file named test_update.conf. Use the same configuration as the write test, but change createTableBeforeRun to false:

    The only change from the write test configuration is createTableBeforeRun=false. This preserves the existing table and data.
       # Connection configuration
       holoClient.jdbcUrl=jdbc:hologres://<ENDPOINT>:<PORT>/<DBNAME>
       holoClient.username=<AccessKey_ID>
       holoClient.password=<AccessKey_Secret>
       holoClient.writeThreadSize=100
    
       # Write configuration
       put.threadSize=8
       put.testByTime=false
       put.rowNumber=200000000
       put.testTime=600000
    
       # Table configuration
       put.tableName=kv_test
       put.columnCount=20
       put.columnSize=20
       put.orientation=row
    
       # Other configurations
       put.createTableBeforeRun=false
       put.deleteTableAfterDone=false
       put.vacuumTableBeforeRun=false
  2. Run the test:

       java -jar holo-e2e-performance-tool-1.0.0.jar test_update.conf FIXED_COPY
  3. View the results:

       cat result.csv

Partial update

A partial update writes to a subset of the TEXT columns. The writeColumnCount parameter controls how many columns are updated.

  1. Create a file named test_update_part.conf. Add the writeColumnCount parameter to the table configuration section:

    writeColumnCount=10 updates 10 of the 20 TEXT columns (50%). Adjust this ratio to match your workload.
       # Connection configuration
       holoClient.jdbcUrl=jdbc:hologres://<ENDPOINT>:<PORT>/<DBNAME>
       holoClient.username=<AccessKey_ID>
       holoClient.password=<AccessKey_Secret>
       holoClient.writeThreadSize=100
    
       # Write configuration
       put.threadSize=8
       put.testByTime=false
       put.rowNumber=200000000
       put.testTime=600000
    
       # Table configuration
       put.tableName=kv_test
       put.columnCount=20
       put.columnSize=20
       put.writeColumnCount=10
       put.orientation=row
    
       # Other configurations
       put.createTableBeforeRun=false
       put.deleteTableAfterDone=false
       put.vacuumTableBeforeRun=false
  2. Run the test:

       java -jar holo-e2e-performance-tool-1.0.0.jar test_update_part.conf FIXED_COPY
  3. View the results:

       cat result.csv

Run a point query test

Step 1: Create the configuration file

Create a file named test_get.conf:

# Connection configuration
holoClient.jdbcUrl=jdbc:hologres://<ENDPOINT>:<PORT>/<DBNAME>
holoClient.username=<AccessKey_ID>
holoClient.password=<AccessKey_Secret>
holoClient.readThreadSize=32

# Test configuration
get.threadSize=8
get.testTime=300000
get.tableName=kv_test
get.async=true
get.vacuumTableBeforeRun=true
get.keyRangeParams=L1-200000000

# Table initialization configuration (used only in PREPARE_GET_DATA mode)
prepareGetData.rowNumber=200000000
prepareGetData.orientation=row
put.columnCount=20
put.columnSize=20
This example configures asynchronous point queries on a row-oriented table. To test synchronous queries, set get.async=false and adjust threadSize and readThreadSize accordingly (see the parameter table below).

Point query parameters

Module

Parameter

Description

Notes

Connection

readThreadSize

Number of query connections

Asynchronous mode: set to 2-4x threadSize for efficient batching. Synchronous mode: increase to match thread count (for example, 100).

Test

threadSize

Number of threads generating query requests

Asynchronous mode: 8 is a good default on a 64-vCPU instance. Synchronous mode: increase to 500 for higher throughput.

testTime

Test duration in milliseconds

tableName

Target table name

async

Whether to use asynchronous point queries

true: asynchronous (high throughput). false: synchronous (low latency).

vacuumTableBeforeRun

Whether to run VACUUM before the test starts

Running VACUUM forces compaction before querying.

keyRangeParams

Primary key range for queries. Format: <I|L><Start>-<End>

I = INT type, L = BIGINT type. Example: L1-200000000 queries keys from 1 to 200,000,000.

Table init (PREPARE_GET_DATA mode only)

rowNumber

Rows to generate

orientation

Storage format

row or row,column

columnCount

Number of TEXT columns

columnSize

Character length per column

Step 2: Run the test

If the table already has data from the write or update tests, skip data preparation and run the point query directly:

# (Optional) Prepare data -- only if the table has no data
java -jar holo-e2e-performance-tool-1.0.0.jar test_get.conf PREPARE_GET_DATA

# Run the point query test
java -jar holo-e2e-performance-tool-1.0.0.jar test_get.conf GET
To use your own business data instead of generated data, the table must have a single-column primary key of the INT or BIGINT type with consecutive values.

Step 3: View the results

cat result.csv

Result fields

All test modes write results to result.csv in the current directory. The file contains the following fields:

Field

Description

start

Test start time

end

Test end time

count

Total rows processed

qps1

Average QPS over the last 1 minute

qps5

Average QPS over the last 5 minutes

qps15

Average QPS over the last 15 minutes

latencyMean

Average latency (ms). Collected in Insert and GET modes only.

latencyP99

P99 latency (ms). Collected in Insert and GET modes only.

latencyP999

P999 latency (ms). Collected in Insert and GET modes only.

version

Hologres instance version

Benchmark results

The following results were collected on a Hologres V3.0.22 instance with 64 vCPUs, using JDK 11 and Fixed Copy mode. Each scenario used 200 million rows with a column size of 20 characters. The recommended total data volume for a 64-vCPU instance is 40 million to 400 million rows. Column counts tested: 20, 50, and 100. QPS values are taken from the qps1 metric and latency values from latencyMean.

Instance type, table schema, data volume, and concurrency all affect performance significantly. Use these numbers as a baseline and adjust concurrency across multiple test runs for your specific configuration. If CPU utilization is not fully saturated after a test run, increase concurrency to find the optimal throughput.

Choose a storage format

Before reviewing the numbers, use this guide to select the right storage format for your workload:

Workload

Recommended format

Why

Write-heavy, no point queries

Row-oriented

Highest write and update throughput (roughly 3x faster than column-oriented)

Mixed writes and point queries

Row-column hybrid

Supports both high-throughput writes and low-latency point queries

Analytical queries on wide tables

Column-oriented

Optimized for column scans, but write throughput is lower

Partial column updates

Row-oriented

Partial updates on row-oriented tables achieve the highest QPS

20 columns

Storage format

Scenario

Concurrency

QPS (x 10,000)

Latency (ms)

Row-oriented

Write (Fixed Copy)

threadSize=8

88.3

--

Global update (Fixed Copy)

threadSize=8

91.1

--

Partial update (Fixed Copy)

threadSize=8

136.7

--

Point query (async)

threadSize=8, readThreadSize=32

43.6

8.60

Point query (sync)

threadSize=100, readThreadSize=100

26.1

7.88

Column-oriented

Write (Fixed Copy)

threadSize=8

29.9

--

Global update (Fixed Copy)

threadSize=8

18.5

--

Partial update (Fixed Copy)

threadSize=8

12.8

--

Row-column hybrid

Write (Fixed Copy)

threadSize=8

25.0

--

Global update (Fixed Copy)

threadSize=8

17.3

--

Partial update (Fixed Copy)

threadSize=8

17.5

--

Point query (async)

threadSize=8, readThreadSize=32

40.4

8.75

Point query (sync)

threadSize=100, readThreadSize=100

27.0

8.12

50 columns

Storage format

Scenario

Concurrency

QPS (x 10,000)

Latency (ms)

Row-oriented

Write (Fixed Copy)

threadSize=8

41.9

--

Global update (Fixed Copy)

threadSize=8

38.2

--

Partial update (Fixed Copy)

threadSize=8

69.8

--

Point query (async)

threadSize=8, readThreadSize=32

35.7

10.20

Point query (sync)

threadSize=100, readThreadSize=100

24.0

9.28

Column-oriented

Write (Fixed Copy)

threadSize=8

15.5

--

Global update (Fixed Copy)

threadSize=8

11.7

--

Partial update (Fixed Copy)

threadSize=8

6.4

--

Row-column hybrid

Write (Fixed Copy)

threadSize=8

13.7

--

Global update (Fixed Copy)

threadSize=8

10.5

--

Partial update (Fixed Copy)

threadSize=8

11.6

--

Point query (async)

threadSize=8, readThreadSize=32

31.5

12.29

Point query (sync)

threadSize=100, readThreadSize=100

24.2

10.00

100 columns

Storage format

Scenario

Concurrency

QPS (x 10,000)

Latency (ms)

Row-oriented

Write (Fixed Copy)

threadSize=8

24.4

--

Global update (Fixed Copy)

threadSize=8

22.5

--

Partial update (Fixed Copy)

threadSize=8

38.1

--

Point query (async)

threadSize=8, readThreadSize=32

26.6

14.34

Point query (sync)

threadSize=100, readThreadSize=100

21.4

12.12

Column-oriented

Write (Fixed Copy)

threadSize=8

8.4

--

Global update (Fixed Copy)

threadSize=8

6.9

--

Partial update (Fixed Copy)

threadSize=8

3.1

--

Row-column hybrid

Write (Fixed Copy)

threadSize=8

7.6

--

Global update (Fixed Copy)

threadSize=8

5.3

--

Partial update (Fixed Copy)

threadSize=8

6.8

--

Point query (async)

threadSize=8, readThreadSize=32

25.0

15.66

Point query (sync)

threadSize=100, readThreadSize=100

21.4

13.79

Key takeaways

  • Row-oriented tables deliver the highest write throughput -- roughly 3x faster than column-oriented tables for the same column count.

  • Partial updates outperform global updates on row-oriented tables because fewer columns are rewritten. On column-oriented and row-column hybrid tables, global updates may match or exceed partial update throughput.

  • Point query latency is similar between row-oriented and row-column hybrid tables, typically under 10 ms for 20-column tables.

  • Asynchronous point queries achieve higher QPS than synchronous queries, but at slightly higher latency.

  • Write and update throughput decreases as column count increases -- a 100-column row-oriented table achieves roughly 28% of the write QPS of a 20-column table. Point query throughput is less affected, retaining 50-60% of QPS at 100 columns compared to 20 columns.

Troubleshooting

ECS client becomes the bottleneck

Symptom: QPS plateaus despite low CPU utilization on the Hologres instance.

Cause: The ECS instance running the test tool has reached its CPU or network bandwidth limit.

Solution: Monitor ECS CPU and network metrics during the test. If either is saturated, upgrade to a larger ECS instance type or reduce threadSize.

Lower-than-expected QPS

Symptom: QPS is significantly lower than the benchmark results listed above.

Possible causes and solutions:

  1. Insufficient concurrency -- If Hologres CPU utilization is low, increase threadSize (for writes and updates) or readThreadSize (for point queries).

  2. Instance has been upgraded or downgraded -- Performance characteristics differ between fresh and resized instances. Create a new instance for benchmarking.

  3. Network latency -- Confirm that the ECS instance and the Hologres instance are in the same VPC and zone.

  4. Data skew -- If using custom data, uneven distribution key values can concentrate load on a subset of shards.

Connection errors

Symptom: The test tool fails with connection-related exceptions.

Solution: Verify the JDBC connection string, AccessKey ID, and AccessKey secret. Confirm that the Hologres instance allows connections from the ECS instance's VPC.

References