Topik ini menjelaskan kemampuan penulisan ulang kueri (query rewrite) pada Dynamic Tables Hologres, cara menggunakannya, serta batasannya.
Ikhtisar Penulisan Ulang Kueri
Dalam skenario data besar dan gudang data, tabel detail sering kali berisi volume data yang sangat besar—ratusan juta hingga miliaran baris. Kueri bisnis dan analitik umumnya bergantung pada operasi GROUP BY + aggregate multidimensi terhadap tabel detail tersebut. Contohnya termasuk menghitung jumlah pesanan atau nilai barang kotor (GMV) berdasarkan hari, jam, atau kota, atau mengukur jumlah tayangan halaman (PV), pengunjung unik (UV), atau tingkat konversi berdasarkan channel atau perangkat.
Biaya agregasi tinggi: Setiap kueri memindai seluruh tabel detail—atau sebagian besar—dan melakukan agregasi hasil. Hal ini mengonsumsi sumber daya CPU dan I/O yang signifikan.
Beban tinggi pada tabel detail: Ini memengaruhi tugas lain dalam database yang sama atau memerlukan skala keluar (scale-out) secara berkala.
Hologres mendukung Dynamic Tables dan penulisan ulang kueri. Ketika pre-agregasi telah dilakukan pada tabel dasar menggunakan Dynamic Table, pengoptimal (optimizer) dapat secara otomatis menulis ulang kueri agregasi yang menargetkan tabel dasar agar menargetkan Dynamic Table—selama kondisi tertentu terpenuhi. Pendekatan ini menghindari komputasi agregasi yang mahal. Manfaat utamanya meliputi:
Mengurangi beban agregasi pada tabel detail: Metrik yang sering digunakan—seperti jumlah pesanan, GMV, PV, dan UV—dapat dibaca langsung dari Dynamic Table. Hal ini menghilangkan pemindaian dan agregasi berulang pada tabel detail.
Kecepatan respons kueri meningkat secara signifikan: Laporan, analitik swalayan, dan pencarian interaktif merespons lebih cepat saat mengenai Dynamic Table. Beban kerja agregasi turun drastis, latensi berkurang, dan pengalaman pengguna terasa seperti mengkueri tabel lebar.
Tidak berdampak pada pengguna hulu: Analis data dan pengembang bisnis tetap hanya perlu mengetahui model tabel dasar. Tim gudang data atau platform mengelola desain dan pemeliharaan Dynamic Table. Optimasi performa sepenuhnya transparan bagi mereka.
Penulisan ulang kueri Dynamic Table Hologres mendukung skenario berikut:
Dasbor operasional real-time atau near real-time dan Pemantauan.
Analisis BI multidimensi dan unduhan (Downloads).
Akselerasi perhitungan terpadu metrik inti—seperti GMV, volume pesanan, dan jumlah Pengguna aktif.
Penggunaan dan Batasan
Batasan versi: Hanya tersedia di Hologres 4.1 ke atas.
Batasan konsistensi kueri: Penulisan ulang kueri menggunakan hasil refresh terbaru dari Dynamic Table. Dibandingkan dengan status terkini tabel dasar, hal ini memperkenalkan keterlambatan dalam rentang waktu tetap. Ini merupakan konsistensi lemah (weak consistency).
Batasan jenis tabel dasar:
Jenis tabel dasar yang didukung: Tabel internal Hologres, tabel eksternal Paimon (dibuat menggunakan Foreign Table), dan tabel eksternal MaxCompute (dibuat menggunakan Foreign Table).
Jika tabel dasar adalah tabel partisi Hologres, partisi fisik tidak didukung. Partisi logis diperbolehkan.
Tabel eksternal tidak didukung.
Batasan jenis Dynamic Table:
Didukung: Dynamic Table non-partisi dan Dynamic Table partisi logis.
Tidak didukung: Dynamic Table partisi fisik dan Dynamic Table eksternal.
Batasan definisi kueri dalam Dynamic Table:
Kueri hanya mendukung satu tabel. Kueri multi-tabel tidak didukung.
Kueri tidak mendukung agregasi terfilter menggunakan klausa
FILTER—misalnya,sum(x) FILTER (WHERE ...).Kueri tidak mendukung kolom terhitung tambahan dalam daftar SELECT yang bergantung pada hasil agregasi—misalnya,
sum(x)/count(x).
Aktifkan dan Konfigurasikan Penulisan Ulang Kueri
Rekomendasi penggunaan: Paling cocok untuk dasbor, pemantauan, dan analitik di mana latensi tingkat detik hingga menit dapat diterima. Untuk beban kerja yang memerlukan real-time ketat atau rekonsiliasi kritis, kueri langsung ke tabel dasar—atau gunakan solusi konsistensi kuat lainnya.
Aktifkan Penulisan Ulang Kueri
Untuk mengaktifkan penulisan ulang kueri pada kueri tabel dasar, atur parameter GUC hg_enable_query_rewrite saat menjalankan kueri.
Jangan aktifkan ini di tingkat database. Hal ini dapat merusak performa.
-- Aktifkan penulisan ulang kueri (tingkat sesi)
SET hg_enable_query_rewrite = on;
-- Atur di tingkat database (tidak disarankan)
ALTER DATABASE <db_name> SET hg_enable_query_rewrite = on;Aktifkan Penulisan Ulang Kueri untuk Tabel Dinamis
Saat membuat Dynamic Table, gunakan properti allowed_to_rewrite_query untuk mengontrol apakah Dynamic Table tersebut berpartisipasi dalam penulisan ulang kueri. Secara default, Dynamic Table tidak berpartisipasi.
CREATE [ OR REPLACE ] DYNAMIC TABLE [ IF NOT EXISTS ] [<schema_name>.]<table_name> (
[col_name],
[col_name],
[col_name]
)
[LOGICAL PARTITION BY LIST(<partition_key>)]
WITH (
...,
allowed_to_rewrite_query = '[true | false]',
...
)
AS
<query>;Deskripsi parameter:
allowed_to_rewrite_query: Menandai apakah Dynamic Table ini dapat menjadi kandidat untuk penulisan ulang kueri.'true': Mengizinkan penggunaan dalam penulisan ulang kueri.'false': Nilai default. Tidak berpartisipasi dalam penulisan ulang kueri.
Rekomendasi penggunaan:
Untuk Dynamic Table yang dibuat khusus untuk mempercepat kueri agregasi, atur
'true'.Untuk Dynamic Table kompleks yang tidak dapat dimanfaatkan oleh aturan saat ini, atur
'false'. Hal ini mengurangi eksplorasi pengoptimal yang sia-sia.
Ubah Pengaturan Penulisan Ulang Kueri untuk Dynamic Table
Gunakan ALTER DYNAMIC TABLE ... SET untuk mengubah apakah Dynamic Table berpartisipasi dalam penulisan ulang kueri:
ALTER DYNAMIC TABLE [IF EXISTS] [<schema_name>.]<table_name>
SET (allowed_to_rewrite_query = '[true | false]');Kontrol Dynamic Table Mana yang Dapat Ditulis Ulang
Saat terdapat beberapa Dynamic Table, gunakan hint untuk menentukan set kandidat. Hal ini mempersempit ruang pencarian pengoptimal dan mengontrol prioritas. Lihat HINT untuk sintaks hint lengkap.
SELECT /*+HINT query_rewrite_candidates(<schema.dt_name1> <schema.dt_name2> ...) */
...
FROM ...;Catatan penggunaan GUC:
Pisahkan beberapa nama Dynamic Table dengan spasi.
Anda dapat menyertakan nama skema.
Contoh:
-- Izinkan hanya dt_sales dalam penulisan ulang kueri
SELECT /*+HINT query_rewrite_candidates(dt_sales) */
day, hour, min(amount), max(amount)
FROM base_sales_table
GROUP BY day, hour;Fitur yang Didukung
Versi saat ini mendukung penulisan ulang kueri untuk agregasi satu tabel. Fitur ini mencakup tiga pola:
Penulisan ulang transparan ketika dimensi agregasi persis sama.
Aggregation roll-up (penggabungan dimensi GROUP BY).
Aggregation roll-up dengan kompensasi kondisi (roll-up dengan filter WHERE).
Pencocokan Persis Dimensi Agregasi
Kondisi:
Dimensi
GROUP BYdalam kueri harus persis sama dengan dimensiGROUP BYdalam definisi Dynamic Table.Fungsi agregasi dalam kueri harus dipetakan langsung ke kolom hasil agregasi yang sudah ada di Dynamic Table.
Semua jenis fungsi agregasi—termasuk DISTINCT—didukung, selama Dynamic Table sudah berisi kolom hasil yang sesuai.
Contoh:
-- Buat tabel dasar
CREATE TABLE base_sales_table(
day text not null,
hour int,
amount int
);
-- Masukkan data
INSERT INTO base_sales_table
VALUES ('20250529', 12, 1),
('20250529', 12, 2),
('20250529', 12, 2),
('20250529', 13, 3),
('20250530', 13, 4),
('20250530', 14, 5),
('20250531', 14, 6);
-- Dynamic table
CREATE DYNAMIC TABLE dt_sales
WITH (
freshness = '1 minutes',
auto_refresh_mode='incremental',
auto_refresh_enable='false',
allowed_to_rewrite_query='true'
)
AS
SELECT
day,
hour,
min(amount),
max(amount),
sum(amount),
count(amount),
count(*) as rows,
count(1) as rows1,
count(distinct amount) as cd
FROM base_sales_table
GROUP BY day, hour;
REFRESH TABLE dt_sales;Contoh kueri: Saat dimensi cocok, rencana eksekusi menunjukkan bahwa kueri tabel dasar ditulis ulang untuk memindai Dynamic Table.
-- Kueri dengan dimensi yang cocok
EXPLAIN SELECT day, hour, min(amount), max(amount) FROM base_sales_table GROUP BY day, hour;
Aggregation roll-up
Kondisi:
Dimensi
GROUP BYpada Dynamic Table harus merupakan superset dari dimensiGROUP BYpada kueri. Dengan kata lain, Dynamic Table mengelompokkan berdasarkan lebih banyak dimensi daripada kueri.Fungsi agregasi dalam kueri harus dapat dihitung ulang dengan mengagregasi ulang kolom yang sudah ada di Dynamic Table.
Fungsi agregasi yang didukung:
min,max,count,sum, danavg.Roll-up berbasis DISTINCT tidak didukung—kecuali dalam kasus pencocokan persis, di mana Dynamic Table sudah menyimpan hasil distinct.
Pemetaan fungsi agregasi:
Fungsi agregasi dalam kueri tabel dasar asli | Kolom agregat yang diperlukan dalam Dynamic Table | Fungsi agregasi setelah penulisan ulang |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Contoh:
-- Buat tabel dasar
CREATE TABLE base_sales_table(
day text not null,
hour int,
amount int
);
-- Masukkan data
INSERT INTO base_sales_table
VALUES ('20250529', 12, 1),
('20250529', 12, 2),
('20250529', 12, 2),
('20250529', 13, 3),
('20250530', 13, 4),
('20250530', 14, 5),
('20250531', 14, 6);
-- Dynamic table: Nonaktifkan auto-refresh untuk memverifikasi penulisan ulang kueri
CREATE DYNAMIC TABLE dt_sales
WITH (
freshness = '1 minutes',
auto_refresh_mode='incremental',
auto_refresh_enable='false',
allowed_to_rewrite_query='true'
)
AS
SELECT
day,
hour,
min(amount),
max(amount),
sum(amount),
count(amount),
count(*) as rows,
count(1) as rows1,
count(distinct amount) as cd
FROM base_sales_table
GROUP BY day, hour;
-- Refresh manual Dynamic Table
REFRESH TABLE dt_sales;Contoh kueri 1: Agregasi hanya berdasarkan hari (roll-up). Kolom GROUP BY pada kueri tabel dasar merupakan subset dari yang didefinisikan dalam Dynamic Table. Maka penulisan ulang berhasil.
-- Kueri asli
EXPLAIN SELECT day, min(amount), max(amount)
FROM base_sales_table
GROUP BY day;
Contoh kueri 2: Roll-up menggunakan sum + count + avg. Kueri tabel dasar menggunakan avg. Dynamic Table menyediakan sum dan count. Maka avg dapat diturunkan. Penulisan ulang diterapkan.
-- Kueri asli
EXPLAIN SELECT day, sum(amount), count(amount), avg(amount)
FROM base_sales_table
GROUP BY day;
Aggregation Roll-Up dengan Kompensasi Kondisi (dengan Filter)
Kondisi:
Kueri tabel dasar mencakup filter WHERE. Namun, definisi Dynamic Table tidak boleh mengandung filter
WHEREapa pun.Semua bidang yang digunakan dalam klausa WHERE harus muncul dalam dimensi
GROUP BYDynamic Table.Fungsi agregasi yang didukung:
min,max,count,sum, danavg. DISTINCT tidak didukung.
Contoh:
-- Buat tabel dasar
CREATE TABLE base_sales_table(
day text not null,
hour int,
amount int
);
-- Masukkan data
INSERT INTO base_sales_table
VALUES ('20250529', 12, 1),
('20250529', 12, 2),
('20250529', 12, 2),
('20250529', 13, 3),
('20250530', 13, 4),
('20250530', 14, 5),
('20250531', 14, 6);
-- Dynamic table: Nonaktifkan auto-refresh untuk memverifikasi penulisan ulang kueri
CREATE DYNAMIC TABLE dt_sales
WITH (
freshness = '1 minutes',
auto_refresh_mode='incremental',
auto_refresh_enable='false',
allowed_to_rewrite_query='true'
)
AS
SELECT
day,
hour,
min(amount),
max(amount),
sum(amount),
count(amount),
count(*) as rows,
count(1) as rows1,
count(distinct amount) as cd
FROM base_sales_table
GROUP BY day, hour;
-- Refresh manual Dynamic Table
REFRESH TABLE dt_sales;Dalam contoh berikut, kueri tabel dasar memiliki kondisi WHERE. Semua bidang yang difilter muncul dalam daftar GROUP BY. Maka penulisan ulang diterapkan.
EXPLAIN SELECT day, sum(amount), count(amount), avg(amount)
FROM base_sales_table
WHERE day > '20250528' AND day <= '20250531'
GROUP BY day;
Periksa Status Penulisan Ulang Kueri
Setelah mengaktifkan penulisan ulang kueri, gunakan salah satu metode berikut untuk memastikan apakah suatu kueri mengenai Dynamic Table.
Periksa rencana eksekusi: Dalam hasil EXPLAIN, lihat nama tabel yang dipindai oleh operator Scan untuk menentukan apakah Dynamic Table terkena.
Periksa log kueri lambat: Di tabel
hologres.hg_query_log, bidangextended_infomencatat Dynamic Table mana yang dipilih. Jika penulisan ulang gagal, penyebab kesalahan juga muncul di sana.
select extended_info::json->>'rewrite_query_info' from hologres.hg_query_log where query_id = 'xxxxx';
?column?
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"rewrite_failed_dt": [[\"public.dt3\", {\"rewrite_failed_cause\": \"Doesn't include all query required output columns\"}]], \"rewrite_succeeded_and_selected_dt\": [\"public.dt2\"], \"rewrite_succeeded_but_not_selected_dt\": [\"public.dt1\"]}
(1 row)Contoh
Contoh 1: Penulisan Ulang Kueri dengan Tabel Dasar Internal Hologres
Tabel dasar berasal dari dataset TPC-H lineitem (100 GB). Untuk langkah pembuatan dan impor tabel, lihat Impor Satu Klik Dataset Publik. Dalam contoh ini, Dynamic Table menggunakan refresh bertahap dan bersifat non-partisi.
CREATE DYNAMIC TABLE dt_lineitem_100g_incremental
WITH (
freshness = '10 minutes',
auto_refresh_mode='incremental',
auto_refresh_enable='false',
allowed_to_rewrite_query='true')
AS
select
l_returnflag,
l_linestatus,
l_shipdate,
sum(l_quantity) as sum_qty,
count(*) as count_order
from
hologres_dataset_tpch_100g.lineitem
group by
l_returnflag,
l_linestatus,
l_shipdate
-- Refresh manual
REFRESH DYNAMIC TABLE dt_lineitem_100g_incremental;Kueri tabel dasar:
set hg_enable_query_rewrite = on;
explain
select
l_returnflag,
l_linestatus,
l_shipdate,
sum(l_quantity) as sum_qty,
count(*) as count_order
from
hologres_dataset_tpch_100g.lineitem
where l_shipdate = '1998-12-01'
group by
l_returnflag,
l_linestatus,
l_shipdateRencana eksekusi menunjukkan bahwa kueri ditulis ulang untuk memindai Dynamic Table:

Hasil dari mengkueri tabel dasar:
l_returnflag | l_linestatus | l_shipdate | sum_qty | count_order
--------------+--------------+------------+----------+-------------
N | O | 1998-12-01 | 52841.00 | 2070
(1 row)Kueri langsung ke Dynamic Table (auto-refresh dinonaktifkan di sini; hanya satu refresh manual yang dijalankan). Hasilnya sesuai dengan refresh terakhir:
select
l_returnflag,
l_linestatus,
l_shipdate,
sum_qty,
count_order
from
dt_lineitem_100g_incremental
where l_shipdate = '1998-12-01' ;
l_returnflag | l_linestatus | l_shipdate | sum_qty | count_order
--------------+--------------+------------+----------+-------------
N | O | 1998-12-01 | 52841.00 | 2070
(1 row)Contoh 2: Penulisan Ulang Kueri dengan Tabel Dasar Eksternal Paimon
Penulisan ulang kueri juga berfungsi ketika tabel dasar adalah tabel eksternal Paimon. Langkah-langkahnya:
Persiapkan tabel Paimon: Impor tabel TPC-H customer 100 GB ke Paimon. Lihat Tabel Paimon untuk detailnya.
Buat tabel eksternal Paimon di Hologres: Gunakan metode Foreign Table. Lihat Akses Katalog Paimon Menggunakan DLF.
-- Buat server eksternal
CREATE SERVER IF NOT EXISTS paimon_server FOREIGN DATA WRAPPER dlf_fdw OPTIONS (
catalog_type 'paimon',
metastore_type 'dlf-rest',
dlf_catalog '<dlf_catalog_name>'
);
-- Impor skema Paimon sebagai tabel eksternal
IMPORT FOREIGN SCHEMA <schema_name>
limit to (customer)
FROM SERVER paimon_server into public
options (if_table_exist 'update');
-- Kueri data
SELECT * FROM customerBuat Dynamic Table untuk mengonsumsi tabel eksternal Paimon secara bertahap: Bangun Dynamic Table di Hologres yang melakukan refresh bertahap dari tabel eksternal Paimon. Auto-refresh dinonaktifkan di sini untuk menyederhanakan verifikasi.
-- Buat Dynamic Table
CREATE DYNAMIC TABLE dt_paimon_customer
WITH (
freshness = '10 minutes',
auto_refresh_mode='incremental',
auto_refresh_enable='false',
allowed_to_rewrite_query='true')
AS
SELECT
c_custkey,
avg(c_acctbal) ,
sum(c_acctbal) ,
count(c_acctbal)
FROM customer
group by c_custkey;
-- Refresh manual Dynamic Table
REFRESH DYNAMIC TABLE dt_paimon_customer;Kueri tabel eksternal Paimon dengan penulisan ulang kueri diaktifkan.
set hg_enable_query_rewrite = on;
SELECT
c_custkey,
avg(c_acctbal) ,
sum(c_acctbal) ,
count(c_acctbal)
FROM
customer
group by c_custkey ORDER BY 3 DESC LIMIT 3;
c_custkey | avg |sum |count
----------|-------------|---------|-----
3605586 |9999.990000 | 9999.99 |1
10705496 |9999.990000 |9999.99 |1
14959900 |9999.990000 |9999.99 |1Kueri Dynamic Table: Hasil mencerminkan refresh terbaru.
SELECT * FROM dt_paimon_customer ORDER BY 3 DESC LIMIT 3;
c_custkey | avg |sum |count
----------|-------------|---------|-----
3605586 |9999.990000 | 9999.99 |1
10705496 |9999.990000 |9999.99 |1
14959900 |9999.990000 |9999.99 |1Konfirmasi melalui rencana eksekusi: Rencana menunjukkan bahwa kueri ditulis ulang untuk mengakses Dynamic Table.
