Amazon Redshift RG Instances vs RA3 Instances - Comparing Cluster Performance and Cost Using TPC-H 10GB

Amazon Redshift RG Instances vs RA3 Instances - Comparing Cluster Performance and Cost Using TPC-H 10GB

We benchmarked Amazon Redshift's new Graviton-based RG instances against RA3 using TPC-H 10GB. Results cover query latency, load performance, and cost efficiency at Tokyo region pricing.
2026.05.17

This page has been translated by machine translation. View original

I'm Ishikawa from the Cloud Business Division. On 5/14, Amazon Redshift's new-generation RG instances (Graviton-based) were announced. Today, I measured and compared the performance difference between the new-generation RG instances (Graviton-based) and the conventional RA3 instances using TPC-H 10GB.

https://dev.classmethod.jp/articles/amazon-redshift-rg-instances-graviton/

In May 2026, AWS released RG instances (AWS Graviton-based, with an integrated data lake query engine) as new compute nodes for Amazon Redshift. The official AWS blog announces the following performance and cost improvements over the conventional RA3 instances.

Comparison item RG advertised value (vs. RA3)
Data warehouse workloads Up to 2.2x
Apache Iceberg queries Up to 2.4x
Apache Parquet queries Up to 1.5x
Price per vCPU 30% reduction

These are peak values under ideal conditions, so reproducibility on real workloads needs to be verified on your own. This time, I prepared both a rg.xlarge × 2 nodes cluster and a ra3.xlplus × 2 nodes cluster in us-east-1, and measured the latency of 22 queries against TPC-H 10GB local tables within a 2-hour window.

https://dev.classmethod.jp/articles/20260516-amazon-redshift-benchmark-data/

Conclusion first

Comparing rg.xlarge × 2 and ra3.xlplus × 2 in us-east-1 with TPC-H 10GB, I confirmed the following.

  • Query latency: median speedup across the 22 queries 1.51x (total 7.52 seconds → 11.26 seconds)
  • Cost efficiency (estimated with Tokyo region pricing): yen-per-query ratio for the same workload 0.47 (rg is about 53% cheaper)
  • COPY load performance: total speedup across 8 tables 1.38x (83 seconds → 114 seconds)

Test environment

Item RG cluster (rg2) RA3 cluster (xlplus2)
Instance type rg.xlarge ra3.xlplus
Number of nodes 2 2
vCPU / node 4 4
Memory / node 32 GB 32 GB
Storage Redshift Managed Storage Redshift Managed Storage
Region us-east-1 us-east-1
Target schema tpch10g tpch10g
Parameter group default.redshift-2.0 default.redshift-2.0

rg.xlarge and ra3.xlplus are identical in vCPU and memory specs. The major difference is that RG is based on AWS Graviton and has a built-in "integrated query engine for data warehouse and data lake".

TPC-H 10GB data from AWS Labs CloudDataWarehouseBenchmark (8 tables, about 86.59 million rows) was COPYed into both clusters in advance.

https://github.com/awslabs/amazon-redshift-utils/tree/master/src/CloudDataWarehouseBenchmark

Let's try it

The test proceeded as follows.

Prerequisites

  • Both clusters are in available state, with TPC-H 10GB already COPYed into the tpch10g schema
  • Region: us-east-1
  • Connection: Redshift Data API (batch-execute-statement / describe-statement)
  • Measurement PC: MacBook

Preparation: aligning the state of both clusters

Factors that can greatly change query performance comparison results include differences in (1) data row counts and statistics, (2) Result Cache, (3) Concurrency Scaling, and (4) search_path. I aligned each of them as follows.

Row count verification and statistics update

I retrieved the row counts of the 8 TPC-H tables on both clusters to confirm an exact match, and re-ran ANALYZE to refresh statistics. The results matched exactly on both clusters.

Table Row count
region 5
nation 25
supplier 100,000
customer 1,500,000
part 2,000,000
partsupp 8,000,000
orders 15,000,000
lineitem 59,986,052
Total About 86.59 million rows

Next, I ran ANALYZE on all 8 tables on both clusters. execute-statement accepts only a single SQL statement, so I used batch-execute-statement to bundle multiple statements into one request.

for CLUSTER in rg2 xlplus2; do
  aws redshift-data batch-execute-statement \
    --cluster-identifier ${CLUSTER} --database dev --db-user awsuser \
    --region us-east-1 \
    --sqls "ANALYZE tpch10g.region" "ANALYZE tpch10g.nation" \
            "ANALYZE tpch10g.supplier" "ANALYZE tpch10g.customer" \
            "ANALYZE tpch10g.part" "ANALYZE tpch10g.partsupp" \
            "ANALYZE tpch10g.orders" "ANALYZE tpch10g.lineitem"
done

Comparing table distribution

Using SVV_TABLE_INFO, I check that the compressed table size, distribution key, and skew are aligned across both clusters.

aws redshift-data execute-statement \
  --cluster-identifier rg2 --database dev --db-user awsuser --region us-east-1 \
  --sql "SELECT \"table\", size, tbl_rows, skew_rows, sortkey1, diststyle
         FROM svv_table_info WHERE schema='tpch10g' ORDER BY \"table\""

Both clusters matched completely, down to size / tbl_rows / diststyle / sortkey1 (the same column compression with AUTO(ENCODE), and identical KEY distribution).

Table size (MB) dist key sort key
region 36 KEY(r_regionkey) r_regionkey
nation 56 KEY(n_nationkey) n_nationkey
supplier 80 KEY(s_suppkey) s_suppkey
part 176 KEY(p_partkey) p_partkey
customer 200 KEY(c_custkey) c_custkey
partsupp 532 KEY(ps_partkey) ps_partkey
orders 768 KEY(o_orderkey) o_orderdate
lineitem 2,765 KEY(l_orderkey) l_shipdate

Disabling Result Cache and setting search_path

To compare raw query performance, Result Cache must be reliably disabled. When the Redshift Data API receives multiple statements such as SET ...; SELECT ... via execute-statement, it processes only the leading SET. So in the benchmark script described later, I used batch-execute-statement to run SET enable_result_cache_for_session = OFF and the TPC-H query consecutively within one session.

Also, so that the tpch10g schema can be accessed without qualification, I persistently set awsuser's search_path on both clusters.

for CLUSTER in rg2 xlplus2; do
  aws redshift-data execute-statement \
    --cluster-identifier ${CLUSTER} --database dev --db-user awsuser \
    --region us-east-1 \
    --sql "ALTER USER awsuser SET search_path = tpch10g, public"
done

Scenario ①: COPY load performance

I cite the two evidence/<run_id>/copy_durations.tsv files captured at cluster creation and compare load times per table. duration_ms is the value returned by aws redshift-data describe-statement --query Duration (nanoseconds) converted to ms.

Table rg2 duration (ms) xlplus2 duration (ms) speedup (xlplus2 / rg2)
region 563 1,060 1.88
nation 591 983 1.66
supplier 1,006 1,413 1.40
customer 2,567 3,299 1.29
part 2,457 3,237 1.32
partsupp 8,480 11,003 1.30
orders 12,713 16,754 1.32
lineitem 54,557 76,429 1.40
Total 82,934 (about 83.0 seconds) 114,178 (about 114.2 seconds) About 1.38

The total load time for the 8 tables was about 83 seconds for rg2 and about 114 seconds for xlplus2, so RG completed the load about 1.38x faster. In particular, for the largest table lineitem (about 60 million rows / 2.7GB), it was 54.6 seconds vs. 76.4 seconds, giving the impression that Graviton plus the integrated I/O engine works consistently well even on large tables.

The small region / nation tables show large speedup ratios, but their absolute values are on the order of ms, so the interpretation requires caution.

Scenario ②: TPC-H 22-query latency measurement

Target queries (all 22 TPC-H queries)

TPC-H 10GB is small, and 22 queries × 3 runs × 2 clusters = 132 executions is expected to fit within 60 minutes, so all 22 standard queries are targeted. This covers all characteristics: short/medium/long time ranges, and JOIN/aggregation/subquery/Window/CASE.

https://github.com/awslabs/amazon-redshift-utils/blob/master/src/CloudDataWarehouseBenchmark/Cloud-DWB-Derived-from-TPCH/10GB/queries/query_0.sql

Q# Time category Main characteristics Where RG is expected to help
Q1 Short Large aggregation on single table lineitem CPU / I/O
Q2 Medium Multi-table join + subquery Optimizer
Q3 Short 3-table join + aggregation CPU
Q4 Short Semi-join EXISTS Subquery optimization
Q5 Medium 6-table join + yearly aggregation Redistribution
Q6 Short Single table lineitem + range predicate I/O / pruning
Q7 Medium 7-table join + yearly aggregation JOIN order
Q8 Medium 8-table join + ratio calculation Aggregation + join
Q9 Long 6-table join + large aggregation CPU / I/O
Q10 Medium 4-table join + Top-N Sort
Q11 Medium Subquery + GROUP BY HAVING Aggregation
Q12 Short lineitem + orders + CASE aggregation I/O / CASE
Q13 Medium Outer join + aggregation NULL handling
Q14 Short lineitem + part + CASE ratio CPU
Q15 Medium View (WITH) + join CTE expansion
Q16 Medium NOT IN + multi-column aggregation Anti-join
Q17 Medium Correlated subquery Subquery optimization
Q18 Medium 3-table join + Top-N Sort / join
Q19 Short lineitem + part + compound OR Filter optimization
Q20 Medium Nested subquery + semi-join Subquery optimization
Q21 Long Self-join (lineitem 3 times) Join redistribution
Q22 Short Subquery + aggregation Aggregation

Benchmark script

The 22 queries are concatenated in a single file at Cloud-DWB-Derived-from-TPCH/10GB/queries/query_0.sql under AWS Labs CloudDataWarehouseBenchmark. I split this into 22 files with Python, rewrote only Q15 into a WITH clause because it required a revenue view, and then submitted them sequentially via batch-execute-statement from the Bash-based run_benchmark.sh.

# Main part of run_benchmark.sh
run_sql() {
  local sql_raw="$1"
  local label="$2"
  local batch_id
  batch_id=$(aws redshift-data batch-execute-statement \
    --cluster-identifier "${CLUSTER}" \
    --database "${DATABASE}" \
    --db-user "${DB_USER}" \
    --region "${REGION}" \
    --statement-name "${TARGET}-${label}" \
    --sqls "SET enable_result_cache_for_session = OFF" "${sql_raw}" \
    --query 'Id' --output text)
  # Wait for completion + use Duration of result SubStatement[1]
}

The measurement policy is as follows.

Item Setting
Number of runs 1 warm-up run + 3 measured runs
Evaluation value Median of Data API Duration (nanoseconds)
Result Cache Always run SET enable_result_cache_for_session = OFF first
Clusters rg2 / xlplus2 launched in parallel from the terminal

Each execute-statement runs in a new session, so bundling the SET statement and the main query in the same session with batch-execute-statement reliably turns off Result Cache. Running Q01 three times as an initial warm-up gave a stable dur=604/615/615 ms, confirming through measurement that Result Cache was not taking effect.

Measurement results (median ms)

# Launch rg2 / xlplus2 simultaneously from separate terminals
./scripts/run_benchmark.sh --target rg2 --cluster-identifier rg2 \
  --database dev --db-user awsuser --region us-east-1 --iterations 3
./scripts/run_benchmark.sh --target xlplus2 --cluster-identifier xlplus2 \
  --database dev --db-user awsuser --region us-east-1 --iterations 3

1 warm-up run + 3 measured runs (88 executions in total × 2 clusters = 176 executions) completed with FINISHED status for all queries on both clusters. The median values and speedups are summarized below.

Query rg2 median (ms) xlplus2 median (ms) speedup (xlplus2 / rg2)
Q01 605 907 1.50
Q02 238 389 1.63
Q03 225 313 1.39
Q04 192 279 1.45
Q05 277 364 1.31
Q06 64 77 1.20
Q07 256 384 1.50
Q08 268 414 1.54
Q09 524 774 1.48
Q10 354 540 1.53
Q11 139 207 1.49
Q12 134 203 1.51
Q13 806 1,334 1.66
Q14 132 173 1.31
Q15 176 271 1.54
Q16 417 632 1.52
Q17 266 386 1.45
Q18 889 1,179 1.33
Q19 318 491 1.54
Q20 248 418 1.69
Q21 707 1,079 1.53
Q22 289 448 1.55
Total 7,524 ms 11,262 ms 1.50

Aggregating the speedups of the 22 queries gives the following.

  • Median speedup: 1.51x
  • Average speedup: 1.48x
  • Maximum speedup: 1.69x (Q20: nested subquery + semi-join)
  • Minimum speedup: 1.20x (Q06: single table lineitem + range predicate, already short at 64ms)

The advertised "up to 2.2x" was not reached, but that is a peak value, and I think around 1.5x on average across the 22 queries is a reasonable level. Queries with many joins and semi-joins such as Q13 and Q20, and heavy aggregation queries such as Q01 and Q21 showed 1.5 to 1.7x, giving the impression that the heavier the workload, the greater the benefit.

Scenario ③: Cost efficiency (yen / query, assuming the Tokyo region)

The latency measurements themselves were done in us-east-1, but assuming real-world operation, I estimate yen / query using the on-demand pricing of the Tokyo region (ap-northeast-1). The prices are the values obtained via aws pricing get-products on the test date (2026-05-17), the exchange rate is an approximate TTM of 1 USD = ¥150, and I calculate with the following formulas.

aws pricing get-products --service-code AmazonRedshift --region us-east-1 \
  --filters "Type=TERM_MATCH,Field=instanceType,Value=rg.xlarge" \
            "Type=TERM_MATCH,Field=location,Value=Asia Pacific (Tokyo)" \
            "Type=TERM_MATCH,Field=productFamily,Value=Compute Instance"

Cluster running cost (yen/second) = node price (USD/h) × number of nodes × exchange rate (JPY/USD) ÷ 3600
Cost per query (yen) = median latency (seconds) × cluster running cost (yen/second)

Cluster Node price (USD/h, Tokyo) Number of nodes Running cost (yen/second)
rg2 (rg.xlarge) 0.8946 2 ¥0.07455
xlplus2 (ra3.xlplus) 1.278 2 ¥0.10650

Looking at node price alone, rg.xlarge is about 30% cheaper than ra3.xlplus, and multiplying the total median of the 22 queries by the price gives the following.

Metric rg2 xlplus2 rg2 / xlplus2
Total median of 22 queries 7.52 seconds 11.26 seconds 0.67
Total cost of query set ¥0.5609 ¥1.1994 0.47
Average cost per query ¥0.02550 ¥0.05452 —

The cost ratio (rg2 / xlplus2) was 0.47, meaning that running the same 22 queries in the Tokyo region was about 53% cheaper with rg2. The "30% lower vCPU price" and "1.5x faster latency" multiply together, resulting in a nearly 2x difference in cost efficiency.

Latency is the measured value in us-east-1, and cost is estimated with Tokyo region pricing. Latency differences between regions are not considered in this test. Throughput under parallel execution was also not measured, and since the values are calculated from single-run latency × price, they do not reflect concurrent execution performance in actual operation.

Discussion

Here are the points I noticed during the test.

  • On local tables, a latency speedup of about 1.5x on average across the 22 queries appears consistently: Even short queries (Q06: 64ms / Q14: 132ms) showed 1.2 to 1.3x, and heavy queries (Q01, Q13, Q18, Q21, etc., 500ms or more) showed 1.5 to 1.7x, confirming a steady improvement regardless of range. The advertised "up to 2.2x" is a peak value, and I feel a lower ratio than this is realistic for the workload as a whole.
  • Cost efficiency is about 53% lower (Tokyo region conversion): rg.xlarge has a node price about 30% lower than ra3.xlplus (Tokyo: $0.8946/h vs $1.278/h), and on top of that latency is 1.5x faster, so in yen / query it is less than half. The same workload can be run at 1/2 the cost, a result with more impact than just looking at the node price table.
  • COPY load is also about 1.38x faster: Not as much as query performance, but 83 seconds vs. 114 seconds for the 8 TPC-H 10GB tables in total. The effect of Graviton and integrated I/O shows up not only in single queries but also in write workloads. I think the benefit of faster dev environment restores and sample data loading is not small.
  • To correctly disable Result Cache via the Redshift Data API, batch-execute-statement is required: If you send SET ...; SELECT ... with execute-statement, only the leading SET is executed and the statement becomes FINISHED with an empty result set. This time, I submitted SET enable_result_cache_for_session = OFF and the main query as two SQL statements of batch-execute-statement in the same session, and adopted SubStatements[1].Duration.
  • To ensure fairness, how the default.redshift-2.0 parameter groups are aligned also needs checking: Both clusters used default.redshift-2.0 this time, and AutoMV, analyze_threshold_percent, etc. were also left aligned at their defaults. If you seriously want reproducibility it is safer to create a custom parameter group, but even in a defaults-to-defaults comparison, if you align the data, statistics, search_path, and Result Cache, a difference of around 1.5x can be observed consistently.
  • Concurrent execution throughput needs separate verification: Since only single-run latency was measured, behavior under multiple users / parallel queries (Concurrency Scaling, WLM slot contention) needs to be pursued in a separate test. Real E2E from BI tools and behavior evaluation with large-scale ETL are outside the scope of this test.

Finally

Comparing rg.xlarge × 2 and ra3.xlplus × 2 in us-east-1 with TPC-H 10GB, I confirmed the following.

  • Query latency: median speedup across the 22 queries 1.51x (total 7.52 seconds → 11.26 seconds)
  • Cost efficiency (estimated with Tokyo region pricing): yen-per-query ratio for the same workload 0.47 (rg2 is about 53% cheaper)
  • COPY load performance: total speedup across 8 tables 1.38x (83 seconds → 114 seconds)

The advertised value (up to 2.2x) is only a peak value, but even with a relatively light workload like TPC-H 10GB, results of around 1.5x and halved cost were obtained through a deterministic and highly reproducible procedure. I hope this helps those who run RA3 in production and are considering migrating to RG in making their decision.

Performance differences for parallel throughput and Iceberg external tables, and comparisons with larger datasets (100GB, 1TB), will be pursued in separate tests if I get some credits.

https://aws.amazon.com/jp/blogs/aws/amazon-redshift-introduces-aws-graviton-based-rg-instances-with-an-integrated-data-lake-query-engine/

https://aws.amazon.com/jp/about-aws/whats-new/2026/05/amazon-redshift-rg-instances-powered-by-graviton/

https://github.com/awslabs/amazon-redshift-utils/tree/master/src/CloudDataWarehouseBenchmark


コスト最適化、打ちっぱなしで元通りになっていませんか

タグ付けも不要リソースの棚卸しも、施策は打てる。でも続ける仕組みがなければ、コストは数か月でじわじわ戻る。一度きりで終わらせず、FinOpsを組織に定着させる=CCoEの役割。最適化を回し続ける進め方を、無料資料にまとめました。

CCoE総合支援

FinOpsを定着させる資料をもらう

Share this article

AWSのお困り事はクラスメソッドへ