All Products
Search
Document Center

ApsaraDB RDS:Mesin akselerasi AP (rds_duckdb)

Last Updated:Aug 27, 2026

Ekstensi rds_duckdb untuk ApsaraDB RDS for PostgreSQL secara otomatis meneruskan kueri SELECT analitis ke mesin berorientasi kolom DuckDB untuk dieksekusi, sehingga mempercepat kueri kompleks secara signifikan tanpa perubahan pada pernyataan SQL Anda. Topik ini menjelaskan cara meneruskan kueri ke DuckDB setelah ekstensi dan tabel DuckDB dibuat, serta mencakup fitur lanjutan terkait dan metode troubleshooting.

Untuk pertanyaan, diskusi, atau masukan mengenai ekstensi ini, bergabunglah dengan grup DingTalk Ekstensi ApsaraDB RDS for PostgreSQL (ID: 103525002795).

Prasyarat

Sebelum menggunakan fitur ini, pastikan kondisi berikut terpenuhi:

  • Instans utama menjalankan ApsaraDB RDS for PostgreSQL versi 13 hingga 18 dengan versi mesin minor 20260130 atau lebih baru. Untuk mempercepat kueri pada instansi hanya baca (read-only), instansi tersebut harus menjalankan PostgreSQL versi 16 hingga 18 dengan versi mesin minor 20260130 atau lebih baru.

  • Untuk menggunakan partitioned table synchronization atau automatic DuckDB table creation, versi mesin minor harus 20260330 atau lebih baru.

  • Ekstensi rds_duckdb telah dibuat.

Catatan penggunaan

  • rds_duckdb hanya mempercepat kueri SELECT read-only. Pernyataan DML (INSERT, UPDATE, dan DELETE), pernyataan DDL, serta kueri yang melibatkan tabel tanpa tabel DuckDB yang sesuai akan dialihkan kembali ke PostgreSQL secara default.

  • Petunjuk hanya mendukung parameter rds_duckdb.execution dan tidak mendukung parameter lainnya.

  • Jika Anda terhubung ke instans menggunakan DMS, gunakan petunjuk untuk mengaktifkan akselerasi karena DMS menulis ulang pernyataan SQL.

  • Kueri sederhana, seperti point queries dan small-range scans, mungkin berjalan lebih lambat di DuckDB karena overhead penerusan dan startup. Konfigurasikan rds_duckdb.plan_cost_threshold untuk menyaring kueri berbiaya rendah. Untuk informasi selengkapnya, lihat Execution cost threshold (plan_cost_threshold).

Prosedur

Akselerasi kueri terdiri dari tiga langkah: aktifkan akselerasi, verifikasi penerusan kueri, dan lihat log eksekusi.

Langkah 1: Aktifkan akselerasi DuckDB

Gunakan salah satu metode berikut untuk meneruskan kueri SELECT ke DuckDB:

  1. Metode 1: Gunakan petunjuk (tingkat pernyataan)

    Tambahkan petunjuk sebelum pernyataan SELECT. Petunjuk ini hanya berlaku untuk pernyataan tersebut, cocok untuk verifikasi sementara atau mempercepat satu kueri lambat:

    /*+ set(rds_duckdb.execution on) */ SELECT * FROM my_table WHERE id = 1;
  2. Metode 2: Konfigurasikan parameter tingkat sesi

    Jalankan perintah berikut dalam sesi saat ini. Semua kueri yang memenuhi syarat dalam sesi tersebut akan didorong ke DuckDB:

    SET rds_duckdb.execution = on;

Langkah 2: Verifikasi penerusan kueri (EXPLAIN / EXPLAIN ANALYZE)

Periksa rencana eksekusi untuk menentukan apakah suatu pernyataan SQL diteruskan ke DuckDB.

  1. Contoh 1: Kueri satu tabel diteruskan ke DuckDB

    /*+ set(rds_duckdb.execution on) */ EXPLAIN SELECT * FROM test_hint;

    Rencana yang diharapkan berisi Custom Scan (DuckDBScan) dan DuckDB Execution Plan:

                             QUERY PLAN
    ------------------------------------------------------------
     Custom Scan (DuckDBScan)  (cost=0.00..0.00 rows=0 width=0)
       DuckDB Execution Plan:
    
     ┌───────────────────────────┐
     │         SEQ_SCAN          │
     │    ────────────────────   │
     │      Table: test_hint     │
     │   Type: Sequential Scan   │
     │       Projections: a      │
     │                           │
     │          ~0 Rows          │
     └───────────────────────────┘
  2. Contoh 2: Rencana native PostgreSQL dipulihkan setelah penerusan dinonaktifkan

    /*+ set(rds_duckdb.execution off) */ EXPLAIN SELECT * FROM test_hint;

    Rencana yang diharapkan:

          QUERY PLAN
    -----------------------
     Seq Scan on test_hint
    (1 row)

Langkah 3: Lihat log DuckDB (opsional)

Parameter rds_duckdb.enable_log_warning mengontrol apakah pesan WARNING dikembalikan ke klien. Ini membantu Anda mengidentifikasi alasan suatu kueri tidak dieksekusi oleh DuckDB.

  1. Aktifkan output WARNING (berlaku langsung pada tingkat sesi):

    SET rds_duckdb.enable_log_warning = on;
  2. Periksa output klien. Saat enable_log_warning = on, pesan WARNING dikembalikan dalam skenario berikut:

    • Pernyataan SQL dialihkan kembali ke PostgreSQL: Fallback postgres due to ...

    • Operasi tulis tidak didukung: Operasi modifikasi pada tabel DuckDB saat ini tidak didukung; dialihkan ke PG.

    • Pernyataan tidak perlu dieksekusi oleh DuckDB: Statements don't need to be handed over to DuckDB, fallback to PG.

Saat enable_log_warning = off (default), pesan-pesan tersebut ditulis ke log pada level DEBUG1 dan tidak dikembalikan ke klien.

Fitur lanjutan

Fitur-fitur berikut membantu mengoptimalkan performa akselerasi atau memperluas cakupan sinkronisasi. Aktifkan fitur ini sesuai kebutuhan bisnis Anda.

Sinkronisasi DDL otomatis

Perubahan skema (DDL) di ApsaraDB RDS for PostgreSQL dapat disinkronkan secara otomatis ke DuckDB. Parameter berikut mengontrol sinkronisasi tersebut:

Parameter

Deskripsi

Nilai default

rds_duckdb.enable_ddl_replication

Menentukan apakah sinkronisasi DDL diaktifkan.

on

rds_duckdb.ddl_replication_fail_action

Aksi yang diambil saat sinkronisasi gagal: refresh (pembaruan penuh otomatis), conflict (tandai konflik dan hentikan sinkronisasi), atau noop (tidak ada aksi).

refresh

Operasi DDL yang didukung telah diverifikasi:

-- Add a column
ALTER TABLE tbl ADD COLUMN extra_1 int;
-- Drop a column
ALTER TABLE tbl DROP COLUMN extra_1;
-- Add a column with a default value
ALTER TABLE tbl ADD COLUMN extra_1 int DEFAULT 0;
-- Drop the default value
ALTER TABLE tbl ALTER COLUMN extra_1 DROP DEFAULT;
-- Change the column type
ALTER TABLE tbl ALTER COLUMN extra_1 TYPE varchar;
-- Rename a column
ALTER TABLE tbl RENAME COLUMN extra_1 TO extra_2;
-- Rename a table
ALTER TABLE tbl RENAME TO tbl_new;
-- DDL within a transaction
BEGIN;
ALTER TABLE tbl ADD COLUMN extra_3 int;
INSERT INTO tbl VALUES (..., 1);
COMMIT;
-- Roll back DDL by using a savepoint
BEGIN;
SAVEPOINT s1;
ALTER TABLE tbl DROP COLUMN extra_1;
ROLLBACK TO SAVEPOINT s1;
COMMIT;

Contoh operasi DDL yang tidak didukung dan memicu fallback:

-- Change the schema of a table (triggers an automatic full refresh or a conflict based on the fail_action setting)
ALTER TABLE tbl SET SCHEMA nsp1;

-- Drop the primary key (interrupts synchronization, and queries fall back to PostgreSQL)
ALTER TABLE tbl DROP CONSTRAINT tbl_pkey;

Setelah primary key dihapus, tabel memasuki status not syncing dalam duckdb_sync_stat dan kueri tidak lagi dieksekusi oleh DuckDB hingga primary key atau REPLICA IDENTITY dipulihkan dan tabel direfresh secara manual.

Partitioned table synchronization

Catatan

Fitur ini hanya didukung pada instans yang menjalankan versi mesin minor 20260330 atau lebih baru.

rds_duckdb dapat menyinkronkan partitioned tables PostgreSQL (single-level dan multi-level) ke DuckDB.

Untuk menyinkronkan tabel partisi PostgreSQL, Anda harus membuat tabel DuckDB untuk partisi root dan semua partisi leaf. Contoh berikut menunjukkan tabel partisi single-level:

-- Create a partitioned table in PostgreSQL
CREATE TABLE test_partition (
    id int,
    age int,
    primary key (id, age)
) PARTITION BY RANGE (age);

CREATE TABLE test_partition_a PARTITION OF test_partition FOR VALUES FROM (0) TO (18);
CREATE TABLE test_partition_b PARTITION OF test_partition FOR VALUES FROM (18) TO (30);
CREATE TABLE test_partition_c PARTITION OF test_partition FOR VALUES FROM (30) TO (60);

INSERT INTO test_partition SELECT i, i FROM generate_series(0, 59) i;

-- Synchronize the root partition and all leaf partitions to DuckDB
SELECT rds_duckdb.create_duckdb_tables('{test_partition, test_partition_a, test_partition_b, test_partition_c}');

Contoh kueri pada partisi root:

/*+ set(rds_duckdb.execution on) */ EXPLAIN SELECT * FROM test_partition WHERE age >= 10 AND age < 20;

Rencana yang diharapkan (hanya partisi yang terkena dipindai setelah pruning):

 Custom Scan (DuckDBScan)  (cost=0.00..0.00 rows=0 width=0)
   DuckDB Execution Plan:

 ┌───────────────────────────┐
 │           UNION           ├──────────────┐
 └─────────────┬─────────────┘              │
 ┌─────────────┴─────────────┐┌─────────────┴─────────────┐
 │         SEQ_SCAN          ││         SEQ_SCAN          │
 │           Table:          ││           Table:          │
 │      test_partition_a     ││      test_partition_b     │
 │   Type: Sequential Scan   ││   Type: Sequential Scan   │
 │       Projections:        ││       Projections:        │
 │          Filters:         ││          Filters:         │
 │     age>=10 AND age<20││     age>=10 AND age<20│
 └───────────────────────────┘└───────────────────────────┘

Tabel partisi multi-level juga didukung. Contoh:

CREATE TABLE test_multi_partition (
    id serial,
    sale_id int NOT NULL,
    sale_date date NOT NULL,
    amount numeric(15,2) NOT NULL,
    primary key(sale_id, sale_date)
) PARTITION BY RANGE (sale_date);

CREATE TABLE test_multi_partition_a_l1 PARTITION OF test_multi_partition
    FOR VALUES FROM ('2024-1-1') TO ('2025-1-1') PARTITION BY RANGE (sale_date);
CREATE TABLE test_multi_partition_b_l1 PARTITION OF test_multi_partition
    FOR VALUES FROM ('2025-1-1') TO ('2026-1-1') PARTITION BY RANGE (sale_date);

CREATE TABLE test_multi_partition_a_l2_1 PARTITION OF test_multi_partition_a_l1
    FOR VALUES FROM ('2024-1-1') TO ('2024-7-1');
CREATE TABLE test_multi_partition_a_l2_2 PARTITION OF test_multi_partition_a_l1
    FOR VALUES FROM ('2024-7-1') TO ('2025-1-1');
CREATE TABLE test_multi_partition_b_l2_1 PARTITION OF test_multi_partition_b_l1
    FOR VALUES FROM ('2025-1-1') TO ('2025-7-1');
CREATE TABLE test_multi_partition_b_l2_2 PARTITION OF test_multi_partition_b_l1
    FOR VALUES FROM ('2025-7-1') TO ('2026-1-1');

INSERT INTO test_multi_partition (sale_id, sale_date, amount)
SELECT (random() * 100)::int, '2024-01-1'::date + i, (random() * 1000)::numeric(15,2)
FROM generate_series(1, 730) i;

-- Synchronize the partitions at all levels
SELECT rds_duckdb.create_duckdb_tables('{
    test_multi_partition,
    test_multi_partition_a_l1, test_multi_partition_b_l1,
    test_multi_partition_a_l2_1, test_multi_partition_a_l2_2,
    test_multi_partition_b_l2_1, test_multi_partition_b_l2_2
}');
Catatan

Jika partisi leaf tidak disinkronkan, kueri pada partisi root dapat memicu fallback karena beberapa tabel tidak tersedia.

Perubahan DDL pada tabel partisi, seperti ATTACH PARTITION dan DETACH PARTITION, juga dikontrol oleh enable_ddl_replication. Perilaku saat gagal ditentukan oleh ddl_replication_fail_action.

Automatic DuckDB table creation

Catatan

Fitur ini hanya didukung pada instans yang menjalankan versi mesin minor 20260330 atau lebih baru.

Selain memanggil create_duckdb_table() secara manual, Anda dapat menggunakan rds_duckdb untuk automatically create tabel DuckDB. Setelah pembuatan otomatis diaktifkan, ketika Anda menjalankan CREATE TABLE di PostgreSQL dan kondisi sinkronisasi terpenuhi, sistem secara otomatis membuat tabel DuckDB yang sesuai dan memulai sinkronisasi inkremental.

-- Enable automatic creation (USERSET level; can be controlled at the session level)
SET rds_duckdb.auto_create_duckdb_table = on;

-- Create a table in PostgreSQL, and the DuckDB table is automatically created
CREATE TABLE auto_tbl(id int primary key, val text);
INSERT INTO auto_tbl VALUES (1, 'hello');

-- Query DuckDB data directly
/*+ set(rds_duckdb.execution on) */ SELECT * FROM auto_tbl;

Hasil yang diharapkan (saat sinkronisasi normal):

  sync_table     | sync_status_description | sync_error_description
-----------------+-------------------------+------------------------
 public.auto_tbl | data syncing            | no errors

Catatan perilaku:

  • Fitur ini hanya berlaku untuk regular tables. Pembuatan otomatis untuk tabel partisi tidak didukung pada versi saat ini.

  • Tabel harus memiliki primary key atau REPLICA IDENTITY. Jika tidak, tabel tidak dapat memasuki status data syncing.

  • Pembuatan otomatis tidak dipicu jika belum ada tabel DuckDB yang dibuat di database saat ini.

Fallback policy

Saat suatu pernyataan SQL tidak memenuhi syarat untuk dieksekusi oleh DuckDB, parameter rds_duckdb.enable_fallback menentukan perilaku:

  • on (default): Kueri secara otomatis dialihkan kembali ke PostgreSQL. Anda dapat mengonfigurasi enable_log_warning untuk melihat alasan fallback.

  • off: Kesalahan langsung dikembalikan untuk mengungkap masalah tersebut.

Selain itu, fallback juga didukung untuk keterlambatan sinkronisasi inkremental yang berlebihan. Parameter rds_duckdb.wait_sync_timeout menentukan periode maksimum waktu tunggu kueri untuk posisi sinkronisasi inkremental. Satuan: milidetik:

Nilai

Deskripsi

-1 (default)

Posisi sinkronisasi tidak diperiksa, dan kueri langsung dieksekusi.

0

LSN langsung dibandingkan tanpa menunggu.

> 0

Kueri menunggu hingga jumlah milidetik yang ditentukan. Jika posisi sinkronisasi DuckDB masih tertinggal dari posisi commit transaksi saat ini, fallback dipicu atau kesalahan dikembalikan.

Skenario pemicu: Jika penulisan sering terjadi dan keterlambatan sinkronisasi tinggi, kueri yang memerlukan konsistensi kuat dapat dialihkan kembali karena timeout tunggu.

Contoh log (enable_log_warning = on):

WARNING:  Fallback postgres due to waiting for incremental synchronization timeout

Jika enable_fallback = off, kesalahan dikembalikan:

ERROR:  RDS DuckDB: canceling statement due to waiting for incremental synchronization timeout

Verifikasi keterlambatan sinkronisasi:

-- View synchronization lag
SELECT slot_name, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes
FROM pg_replication_slots
WHERE slot_name LIKE 'rds_duckdb_slot%';

Execution cost threshold (plan_cost_threshold)

Parameter rds_duckdb.plan_cost_threshold memastikan bahwa hanya kueri dengan perkiraan biaya yang cukup tinggi yang diteruskan ke DuckDB. Hal ini mencegah kueri sederhana berjalan lebih lambat karena overhead penerusan dan startup DuckDB.

Parameter

Nilai default

Deskripsi

rds_duckdb.plan_cost_threshold

0

Ambang batas biaya, dalam satuan yang sama dengan cost pada output EXPLAIN PostgreSQL. Nilai 0 menunjukkan bahwa biaya tidak dievaluasi, dan semua pernyataan SELECT yang memenuhi syarat dicoba di DuckDB.

Skenario khas:

  • Workload online berisi pernyataan SQL analitis kompleks (JOIN, agregasi, dan large scans) serta kueri titik atau small-range scans yang sederhana. Yang terakhir berjalan lebih cepat di PostgreSQL karena DuckDB memiliki overhead tetap untuk penerusan dan inisialisasi koneksi.

  • Jika Anda menetapkan ambang batas yang sesuai, seperti 1000 atau 10000, kueri sederhana berbiaya rendah tetap berjalan di PostgreSQL, dan hanya kueri berat berbiaya tinggi yang didorong ke DuckDB untuk akselerasi.

Contoh konfigurasi:

-- Set the cost threshold to 5000. Only queries whose PostgreSQL plan costs exceed 5000 are forwarded to DuckDB
SET rds_duckdb.plan_cost_threshold = 5000;

-- Example 1: A simple point query whose PostgreSQL plan cost is low remains in PostgreSQL
/*+ set(rds_duckdb.execution on) */ EXPLAIN SELECT * FROM my_table WHERE id = 1;

-- Example 2: A complex aggregation query whose PostgreSQL plan cost is high is forwarded to DuckDB
/*+ set(rds_duckdb.execution on) */ EXPLAIN SELECT count(*), avg(amount) FROM my_table GROUP BY region;
Catatan

Parameter ini hanya memengaruhi tahap evaluasi biaya dan tidak memengaruhi mekanisme fallback. Bahkan jika kueri diteruskan ke DuckDB, kueri tersebut tetap akan dialihkan kembali ke PostgreSQL jika terjadi kesalahan dalam pelaksana DuckDB.

Jika ambang batas terlalu tinggi, kueri berbiaya menengah yang dapat dipercepat mungkin tetap di PostgreSQL. Jika ambang batas terlalu rendah, kueri sederhana tidak dapat disaring. Sesuaikan ambang batas secara bertahap berdasarkan workload aktual Anda.

FAQ

Mengapa kueri tidak dieksekusi oleh DuckDB?

Parameter rds_duckdb.enable_fallback membantu Anda mengidentifikasi alasan spesifik mengapa kueri tidak dieksekusi oleh DuckDB.

Langkah troubleshooting:

-- Step 1: Disable fallback to expose the actual cause
SET rds_duckdb.enable_fallback = off;

-- Step 2: Run the target SQL statement
/*+ set(rds_duckdb.execution on) */ EXPLAIN SELECT * FROM my_table;

Kesalahan yang mungkin terjadi dan artinya:

Error

Arti

"my_table" is not a duckdb table or not in syncing status, and rds_duckdb.enable_fallback is set to off.

Tabel tidak memiliki tabel berorientasi kolom DuckDB yang sesuai atau tidak dalam status syncing.

RDS DuckDB: canceling statement due to not in syncing status.

Saat query_syncing_table = on, tabel belum menyelesaikan sinkronisasi.

RDS DuckDB: canceling statement due to waiting for incremental synchronization timeout

Keterlambatan sinkronisasi melebihi wait_sync_timeout.

Modification operations on DuckDB tables are currently not supported, fallback to PG.

Operasi INSERT, UPDATE, atau DELETE dilakukan pada tabel DuckDB.

Skenario fallback umum:

Skenario

Deskripsi

The table is not a DuckDB table

create_duckdb_table() belum dipanggil.

The table is not in the syncing state

Sinkronisasi awal belum lengkap, terjadi konflik DDL, atau tabel tidak memiliki primary key.

Incremental synchronization timeout

Waktu tunggu sinkronisasi habis berdasarkan pengaturan rds_duckdb.wait_sync_timeout.

Syntax not supported by DuckDB

DuckDB tidak mendukung beberapa fitur SQL, sehingga kueri secara otomatis dialihkan kembali.

The query involves non-DuckDB tables

Beberapa tabel dalam kueri JOIN tidak memiliki tabel DuckDB.

Kueri status sinkronisasi setiap tabel DuckDB menggunakan tampilan rds_duckdb.duckdb_sync_stat. Diperlukan akun istimewa. Contoh:

SELECT sync_table,
       sync_status_description,
       sync_error_description
FROM rds_duckdb.duckdb_sync_stat;

 sync_table        | sync_status_description | sync_error_description
-------------------+-------------------------+------------------------------------------
 test_schema.test1 | not syncing             | no primary key or replica identity index

Jika Anda ingin mengkueri data dari tabel yang tidak disinkronkan secara inkremental, atur parameter rds_duckdb.query_syncing_table = off.

Link terkait