All Products
Search
Document Center

Hologres:Buat tabel dinamis

Last Updated:Sep 03, 2026

Buat Dynamic Table yang secara otomatis merefresh hasil kueri dari tabel dasar menggunakan incremental refresh atau full refresh.

Catatan penting

  • Batasan penggunaan Dynamic Table: Dukungan dan batasan Dynamic Table.

  • Hologres V3.1 dan versi lebih baru hanya mendukung sintaks baru untuk membuat Dynamic Table. Anda masih dapat melakukan operasi ALTER pada tabel yang dibuat dengan sintaks V3.0, tetapi tidak dapat membuat yang baru. Untuk tabel non-partisi, gunakan perintah konversi sintaks untuk mengonversi sintaks lama ke sintaks baru. Untuk tabel partisi, buat ulang secara manual.

  • Peningkatan ke Hologres V3.1 dan versi lebih baru mengharuskan pembuatan ulang Incremental Dynamic Table yang sudah ada. Anda dapat menggunakan perintah konversi sintaks untuk melakukannya.

  • Di Hologres V3.1+, mesin secara adaptif mengoptimalkan proses refresh. ID kueri negatif untuk operasi refresh adalah hal yang diharapkan.

Sintaks

V3.1+ (sintaks baru)

Catatan

V3.1+ hanya mendukung sintaks baru.

Sintaks Create Dynamic Table

Sintaks untuk membuat Dynamic Table di V3.1+:

CREATE DYNAMIC TABLE [ IF NOT EXISTS ] [<schema_name>.]<table_name>
[ (<col_name> [, ...] ) ]
[LOGICAL PARTITION BY LIST(<partition_key>)]
WITH (
  -- Properti Dynamic Table
  freshness = {'<num> {minutes | hours}' | 'upstream'}, -- Wajib
  [auto_refresh_enable = {true | false},] -- Opsional
  [auto_refresh_mode = {'full' | 'incremental' | 'auto'},] -- Opsional
  
  [base_table_cdc_format = {'stream' | 'binlog'},] -- Opsional

  [auto_refresh_partition_active_time = '<num> {minutes | hours | days}',] -- Opsional
  [partition_key_time_format = {'YYYYMMDDHH24' | 'YYYY-MM-DD-HH24' | 'YYYY-MM-DD_HH24' | 'YYYYMMDD' | 'YYYY-MM-DD' | 'YYYYMM' | 'YYYY-MM' | 'YYYY'},] --Opsional
  
  [computing_resource = {'local' | 'serverless' | '<warehouse_name>'},] -- Opsional. Nilai warehouse_name hanya didukung di Hologres V4.0.7 dan versi lebih baru.
  [refresh_guc_hg_experimental_serverless_computing_required_cores=xxx,] --Opsional. Menentukan jumlah core komputasi yang dibutuhkan untuk Serverless.
  
  [refresh_guc_<guc_name> = '<guc_value>',] -- Opsional

  -- Properti umum
  [orientation = {'column' | 'row' | 'row,column'},]
  [table_group = '<tableGroupName>',]
  [distribution_key = '<columnName>[,...]]',]
  [clustering_key = '<columnName>[:asc] [,...]',]
  [event_time_column = '<columnName> [,...]',]
  [bitmap_columns = '<columnName> [,...]',]
  [dictionary_encoding_columns = '<columnName> [,...]',]
  [time_to_live_in_seconds = '<non_negative_literal>',]
  [storage_mode = {'hot' | 'cold'},]
)
AS
<query>; -- Definisi kueri.

Parameter

Mode Penyegaran dan Sumber Daya

Parameter

Deskripsi

Wajib

Default

freshness

Tingkat kesegaran data target dalam menit atau jam. Minimum: 1 menit. Mesin menjadwalkan refresh berdasarkan waktu refresh sebelumnya dan nilai freshness ini. Berbeda dengan interval tetap, freshness secara adaptif menyesuaikan diri agar data tetap mutakhir. Nilai yang valid:

  • '<num> {minutes | hours}': refresh dijadwalkan secara otomatis berdasarkan freshness yang ditentukan.

  • 'upstream': mode refresh kaskade, didukung di Hologres V5.0 dan versi lebih baru. Tabel ini tidak memiliki jadwal refresh sendiri. Sebaliknya, refresh dipicu setelah Dynamic Table hulu selesai merefresh, sehingga data mengalir bertahap melalui gudang data multi-lapis (ODS ke DWD ke DWS ke ADS) tanpa interval refresh terpisah untuk setiap lapisan. Saat menggunakan nilai ini, minimal satu dari tabel dasar harus berupa dynamic table. Jika tidak, pembuatan tabel akan gagal. Untuk perilaku pemicu, lihat Refresh kaskade.

Ya

Tidak ada

auto_refresh_mode

Mode refresh. Nilai yang valid:

  • auto: Mode otomatis. Mesin secara otomatis menggunakan incremental refresh jika kueri mendukungnya; jika tidak, beralih ke full refresh.

  • incremental: Incremental refresh. Hanya data inkremental yang direfresh setiap kali. Untuk informasi lebih lanjut, lihat Incremental refresh.

  • full: Full refresh. Seluruh tabel direfresh setiap kali. Untuk informasi lebih lanjut, lihat Full refresh.

Tidak

auto

auto_refresh_enable

Mengaktifkan atau menonaktifkan refresh otomatis. Nilai yang valid:

  • true: Mengaktifkan refresh otomatis.

  • false: Menonaktifkan refresh otomatis. Semua pekerjaan refresh selanjutnya untuk tabel ini dihentikan.

Tidak

true

base_table_cdc_format

Cara mengonsumsi perubahan data tabel dasar selama incremental refresh.

  • stream (default): Membaca perubahan data tingkat file. Tidak ada overhead penyimpanan tambahan dan performa lebih tinggi daripada binlog. Untuk informasi lebih lanjut, lihat Dynamic tables.

  • binlog: Mengonsumsi perubahan data tabel dasar melalui binlog. Memerlukan pengaktifan binlog secara manual pada tabel dasar (Subscribe to Hologres Binlog).

    begin;
    call set_table_property('<table_name>', 'binlog.level', 'replica');
    call set_table_property('<table_name>', 'binlog.ttl', '2592000');
    commit;
Catatan
  • Sejak V3.1, semua tabel default ke stream. Nonaktifkan binlog jika diaktifkan untuk menghindari biaya penyimpanan yang tidak perlu.

  • Metode stream tidak didukung untuk tabel dasar berorientasi baris; hanya metode binlog yang didukung.

  • Parameter ini tidak dapat dimodifikasi setelah tabel dibuat. Untuk mengubahnya, buat ulang tabel tersebut.

Tidak

stream

computing_resource

Sumber daya komputasi untuk refresh. Nilai yang valid:

  • serverless (default): Menggunakan sumber daya Serverless Computing, memisahkan beban kerja refresh dari trafik kueri.

  • <warehouse_name>: Menggunakan gudang komputasi yang ditentukan untuk refresh.

    Catatan

    Hanya didukung di Hologres V4.0.7 dan versi lebih baru.

  • local: Menggunakan sumber daya komputasi lokal dari instans saat ini untuk refresh.

Parameter.

Tidak

serverless

refresh_guc_<guc_name>

Atur parameter GUC untuk refresh. Untuk daftar GUC yang didukung, lihat Parameter GUC.

Tidak

Tidak ada

Tabel partisi

Tabel partisi logis

Parameter

Deskripsi

Wajib

Default

LOGICAL PARTITION BY LIST(<partition_key>)

Membuat Dynamic Table partisi logis. Memerlukan auto_refresh_partition_active_time dan partition_key_time_format.

Tidak

Tidak ada

auto_refresh_partition_active_time

Lingkup refresh untuk partisi, dalam menit, jam, atau hari. Hologres melacak mundur dari waktu saat ini dan merefresh partisi dalam jendela ini.

Partisi aktif adalah partisi yang selang waktunya sejak mulai (diturunkan dari nama partisi) kurang dari nilai auto_refresh_partition_active_time.

Catatan
  • Parameter auto_refresh_partition_active_time harus menentukan durasi yang lebih besar dari satu interval partisi. Misalnya, jika data dipartisi harian, auto_refresh_partition_active_time harus diatur ke periode lebih dari 24 jam.

  • Parameter ini dapat dimodifikasi. Perubahan hanya memengaruhi partisi mendatang.

  • Mulai dari Hologres V4.2, merefresh partisi aktif Dynamic Table menggunakan kunci tingkat partisi alih-alih kunci tingkat tabel. Artinya, partisi berbeda dapat direfresh secara konkuren tanpa saling menunggu.

Ya

Default ke Interval partisi + 1 jam.

Ini memberikan buffer 1 jam untuk mengantisipasi potensi keterlambatan data dari tabel dasar. Misalnya, dengan partisi harian, default menjadi 25 jam (1 hari + 1 jam).

partition_key_time_format

Format nama partisi. Nilai yang valid:

  • Untuk kunci partisi TEXT/VARCHAR:

    YYYYMMDDHH24, YYYY-MM-DD-HH24, YYYY-MM-DD_HH24, YYYYMMDD, YYYY-MM-DD, YYYYMM, YYYY-MM, YYYY.

  • Untuk kunci partisi INT:

    YYYYMMDDHH24, YYYYMMDD, YYYYMM, YYYY.

  • Untuk kunci partisi DATE:

    YYYY-MM-DD

Ya

Tidak ada

Tabel partisi fisik

Parameter

Deskripsi

Wajib

Default

PARTITION BY LIST(<partition_key>)

Membuat Dynamic Table partisi fisik.

Dynamic Table partisi fisik tidak memiliki partisi dinamis dan memiliki batasan penggunaan. Partisi logis direkomendasikan. Untuk perbedaan, lihat CREATE LOGICAL PARTITION TABLE.

Penting

Hologres V3.1+ tidak mendukung pembuatan Dynamic Table sebagai tabel partisi fisik.

Tidak

Tidak ada

Properti tabel

Parameter

Deskripsi

Wajib

Nilai default

Full Refresh Mode

Incremental Refresh Mode

col_name

Nama kolom.

Tentukan nama tetapi bukan atribut atau tipe data—mesin akan menginferensinya.

Catatan

Menentukan atribut kolom dan tipe data dapat menyebabkan inferensi mesin salah.

Tidak

Nama kolom kueri

Nama kolom kueri

orientation

Format penyimpanan. column menunjukkan penyimpanan berorientasi kolom.

Tidak

column

column

table_group

Kelompok Tabel. Default ke kelompok default database saat ini. Untuk informasi lebih lanjut, lihat Mengelola kelompok tabel dan shard.

Tidak

Nama Kelompok Tabel default

Nama Kelompok Tabel default

distribution_key

Kunci distribusi. Untuk informasi lebih lanjut, lihat Kunci distribusi.

Tidak

(tidak ada)

(tidak ada)

clustering_key

Kunci pengelompokan. Untuk informasi lebih lanjut, lihat Kunci pengelompokan.

Tidak

Diizinkan, dengan nilai default yang diinferensi.

Diizinkan, dengan nilai default yang diinferensi.

event_time_column

Lihat Kolom waktu event (kunci segmen).

Tidak

(tidak ada)

(tidak ada)

bitmap_columns

Kolom bitmap. Untuk informasi lebih lanjut, lihat Indeks bitmap.

Tidak

Bidang tipe TEXT

Bidang tipe TEXT

dictionary_encoding_columns

Lihat Encoding kamus.

Tidak

Bidang tipe TEXT

Bidang tipe TEXT

time_to_live_in_seconds

TTL data.

Tidak

Tidak kedaluwarsa

Tidak kedaluwarsa

storage_mode

Tingkat penyimpanan. Nilai yang valid:

  • hot: Penyimpanan hot.

  • cold: Penyimpanan cold.

Catatan

Untuk detail, lihat Menyiapkan tiering penyimpanan.

Tidak

hot

hot

binlog_level

Mengaktifkan binlog untuk Dynamic Table. Subscribe to Hologres Binlog.

Catatan
  • Parameter ini memerlukan V3.1.18 dan versi lebih baru.

  • Hindari mengaktifkan binlog untuk Dynamic Table yang menggunakan full refresh.

Tidak

none

none

binlog_ttl

TTL binlog.

Tidak

2592000

2592000

Refresh kaskade

Hologres V5.0 dan versi lebih baru mendukung refresh kaskade. Ketika tabel dasar dari dynamic table mencakup dynamic table lain, Anda dapat mengatur freshness-nya ke 'upstream' sehingga tabel tersebut direfresh secara otomatis setelah dynamic table hulunya selesai merefresh, membentuk rantai refresh kaskade. Pendekatan ini cocok untuk skenario gudang data multi-lapis: atur nilai freshness eksplisit hanya pada akar rantai dan atur setiap lapisan hilir ke 'upstream'. Data kemudian mengalir lapis demi lapis tanpa interval refresh untuk setiap lapisan dan tanpa penjadwal eksternal untuk mengatur dependensi.

Contoh
-- Akar: direfresh dengan freshness tetap.
CREATE DYNAMIC TABLE dwd_orders
WITH (
  auto_refresh_mode = 'incremental',
  freshness = '5 minutes'
)
AS SELECT order_id, user_id, ds, amount FROM ods_orders;

-- Lapisan kedua: dipicu setelah dwd_orders direfresh.
CREATE DYNAMIC TABLE dws_user_amount
WITH (
  auto_refresh_mode = 'incremental',
  freshness = 'upstream'
)
AS SELECT user_id, ds, SUM(amount) AS amt FROM dwd_orders GROUP BY user_id, ds;

-- Lapisan ketiga: dipicu setelah dws_user_amount direfresh.
CREATE DYNAMIC TABLE ads_daily_amount
WITH (
  auto_refresh_mode = 'incremental',
  freshness = 'upstream'
)
AS SELECT ds, SUM(amt) AS amt FROM dws_user_amount GROUP BY ds;

Untuk memantau rantai kaskade, kueri hologres.hg_dynamic_table_refresh_history. Refresh yang dipicu oleh tabel hulu dicatat dengan tipe pemicu cascade.

SELECT dynamic_table_name, refresh_type, status, refresh_start
FROM hologres.hg_dynamic_table_refresh_history
WHERE schema_name = '<SCHEMA_NAME>'
ORDER BY refresh_start;
Perilaku pemicu
  • Pemicu menyebar satu level per satu waktu: ketika dynamic table hulu selesai merefresh, ia memicu tabel hilir langsungnya, dan masing-masing memicu level berikutnya setelah selesai. Tabel hulu tidak pernah memicu cucu langsung. Dalam rantai A ke B ke C, C dipicu oleh B, bukan oleh A.

  • Tabel hulu mengembalikan respons segera setelah refresh-nya sendiri selesai dan tidak menunggu refresh hilir. Hal yang sama berlaku untuk REFRESH DYNAMIC TABLE manual: pernyataan mengembalikan respons ketika tabel saat ini direfresh, dan refresh hilir berjalan secara asinkron setelahnya. Untuk mengontrol apakah refresh manual memicu tabel hilir, gunakan parameter cascading. Untuk informasi lebih lanjut, lihat Refresh dynamic table.

  • Ketika dynamic table memiliki beberapa dynamic table hulu, refresh sukses dari salah satu tabel hulu memicu satu refresh tabel ini tanpa menunggu tabel hulu lainnya. Akibatnya, tabel ini mungkin menggabungkan data terbaru dari beberapa tabel hulu dengan data lama dari yang lain. Ini adalah perilaku yang diharapkan untuk refresh kaskade. Jika bisnis Anda memerlukan semua data hulu selaras, jangan mengandalkan pemicu kaskade. Refresh tabel secara manual setelah semua data hulu siap.

Kueri

Kueri yang mendefinisikan data Dynamic Table. Kueri yang didukung dan tabel dasar bervariasi berdasarkan mode refresh. Untuk informasi lebih lanjut, lihat Dukungan dan batasan Dynamic Table.

V3.0 (sintaks lama)

Sintaks Create Dynamic Table

CREATE DYNAMIC TABLE [IF NOT EXISTS] <schema.tablename>(
[col_name],
[col_name]
  ) [PARTITION BY LIST (col_name)]
WITH (
    [refresh_mode='[full|incremental]',]
    [auto_refresh_enable='[true|false',]

  --Parameter incremental refresh:
    [incremental_auto_refresh_schd_start_time='[immediate|<timestamptz>]',]
    [incremental_auto_refresh_interval='[<num> {minute|minutes|hour|hours]',]  
    [incremental_guc_hg_computing_resource='[ local | serverless]',]
    [incremental_guc_hg_experimental_serverless_computing_required_cores='<num>',]

   --Parameter full refresh:
    [full_auto_refresh_schd_start_time='[immediate|<timestamptz>]',]
    [full_auto_refresh_interval='[<num> {minute|minutes|hour|hours]',] 
    [full_guc_hg_computing_resource='[ local | serverless]',]--hg_full_refresh_computing_resource default ke serverless, dapat diatur di tingkat DB, dan opsional bagi pengguna.
    [full_guc_hg_experimental_serverless_computing_required_cores='<num>',]
    
   --Parameter bersama, GUC diizinkan:
   [refresh_guc_<guc>='xxx]',] 
   
  -- Properti Dynamic Table umum:
    [orientation = '[column]',]
    [table_group = '[tableGroupName]',]
    [distribution_key = 'columnName[,...]]',]
    [clustering_key = '[columnName{:asc]} [,...]]',]
    [event_time_column = '[columnName [,...]]',]
    [bitmap_columns = '[columnName [,...]]',]
    [dictionary_encoding_columns = '[columnName [,...]]',]
    [time_to_live_in_seconds = '<non_negative_literal>',]
    [storage_mode = '[hot | cold]']
    ) 
AS
<query> --Definisi kueri

Parameter

Mode refresh dan sumber daya

Kategori

Parameter

Deskripsi

Wajib

Default

Parameter refresh bersama

refresh_mode

Mode refresh. Nilai yang valid: full dan incremental.

Jika tidak diatur, tidak ada refresh yang dilakukan.

Tidak

(tidak ada)

auto_refresh_enable

Mengaktifkan atau menonaktifkan refresh otomatis. Nilai yang valid:

  • true

  • false

Tidak

false

refresh_guc_<guc>

Atur parameter GUC untuk refresh. Untuk daftar GUC yang didukung, lihat Parameter GUC.

Catatan

Contohnya, untuk mengatur GUC timezone, gunakan refresh_guc_timezone = 'GMT-8:00'.

Tidak

(tidak ada)

Incremental refresh

incremental_auto_refresh_schd_start_time

Waktu mulai untuk incremental refresh. Nilai yang valid:

  • immediate: Default. Memulai incremental refresh segera setelah pembuatan tabel.

  • <timestamptz>: Waktu mulai kustom, misalnya '2024-08-24 1:00', untuk memulai tugas refresh pada waktu tersebut.

Tidak

immediate

incremental_auto_refresh_interval

Interval incremental refresh, dalam menit atau jam.

  • Rentang nilai: [1 menit, 48 jam].

  • Jika tidak diatur, Dynamic Table hanya direfresh sekali, pada waktu mulai.

Tidak

(tidak ada)

incremental_guc_hg_computing_resource

Sumber daya komputasi untuk incremental refresh. Nilai yang valid:

  • local: Gunakan sumber daya instans sendiri.

  • serverless: Gunakan sumber daya Serverless Computing. Untuk memeriksa apakah instans memenuhi persyaratan Serverless Computing, lihat Bekerja dengan komputasi tanpa server.

Catatan

Untuk mengatur sumber daya komputasi di tingkat DB, jalankan ALTER DATABASE xxx SET incremental_guc_hg_computing_resource=xx.

Tidak

local

incremental_guc_hg_experimental_serverless_computing_required_cores

Core Serverless Computing untuk refresh.

Catatan

Kuota sumber daya Serverless Computing bervariasi berdasarkan spesifikasi instans. Untuk informasi lebih lanjut, lihat Mengelola sumber daya komputasi tanpa server.

Tidak

(tidak ada)

Full refresh

full_auto_refresh_schd_start_time

Waktu mulai untuk full refresh. Nilai yang valid:

  • immediate: Default. Memulai full refresh segera setelah pembuatan tabel.

  • <timestamptz>: Waktu mulai kustom, misalnya '2024-08-24 1:00', untuk memulai tugas refresh pada waktu tersebut.

Tidak

immediate

full_auto_refresh_interval

Interval full refresh, dalam menit atau jam.

  • Rentang nilai: [1 menit, 48 jam].

  • Jika tidak diatur, Dynamic Table hanya direfresh sekali, pada waktu mulai.

Tidak

(tidak ada)

full_guc_hg_computing_resource

Sumber daya komputasi untuk full refresh. Nilai yang valid:

  • local: Sumber daya instans sendiri.

  • serverless: Gunakan sumber daya Serverless Computing. Untuk memeriksa apakah instans memenuhi persyaratan Serverless Computing, lihat Bekerja dengan komputasi tanpa server.

Catatan

Untuk mengatur sumber daya komputasi di tingkat DB, jalankan ALTER DATABASE xxx SET full_guc_hg_computing_resource=xx.

Tidak

local

full_guc_hg_experimental_serverless_computing_required_cores

Core Serverless Computing untuk refresh.

Catatan

Kuota sumber daya Serverless Computing bervariasi berdasarkan spesifikasi instans. Untuk informasi lebih lanjut, lihat Mengelola sumber daya komputasi tanpa server.

Tidak

(tidak ada)

Properti tabel

Parameter

Deskripsi

Wajib

Default

full

incremental

col_name

Nama kolom.

Tentukan nama tetapi bukan atribut atau tipe data—mesin akan menginferensinya.

Catatan

Menentukan atribut kolom dan tipe data dapat menyebabkan inferensi mesin salah.

Tidak

Nama kolom kueri

Nama kolom kueri

orientation

Format penyimpanan untuk Dynamic Table. column menunjukkan penyimpanan berorientasi kolom.

Tidak

column

column

table_group

Kelompok Tabel. Default ke kelompok default database saat ini. Untuk informasi lebih lanjut, lihat Mengelola kelompok tabel dan shard.

Tidak

Nama Kelompok Tabel default

Nama Kelompok Tabel default

distribution_key

Kunci distribusi. Untuk informasi lebih lanjut, lihat Kunci distribusi.

Tidak

(tidak ada)

(tidak ada)

clustering_key

Kunci pengelompokan. Untuk informasi lebih lanjut, lihat Kunci pengelompokan.

Tidak

Diizinkan, dengan nilai default yang diinferensi.

Diizinkan, dengan nilai default yang diinferensi.

event_time_column

Kunci segmen. Untuk informasi lebih lanjut, lihat Kolom waktu event (kunci segmen).

Tidak

(tidak ada)

(tidak ada)

bitmap_columns

Kolom bitmap. Untuk informasi lebih lanjut, lihat Indeks bitmap.

Tidak

Bidang tipe TEXT

Bidang tipe TEXT

dictionary_encoding_columns

Lihat Encoding kamus.

Tidak

Bidang tipe TEXT

Bidang tipe TEXT

time_to_live_in_seconds

TTL data.

Tidak

Tidak kedaluwarsa

Tidak kedaluwarsa

storage_mode

Tingkat penyimpanan. Nilai yang valid:

  • hot: Penyimpanan hot.

  • cold: Penyimpanan cold.

Tidak

hot

hot

PARTITION BY LIST

Membuat Dynamic Table partisi. Partisi dapat menggunakan mode refresh berbeda untuk kebutuhan freshness yang bervariasi.

Tidak

Tabel non-partisi

Tabel non-partisi

Kueri

Kueri yang menghasilkan data Dynamic Table. Kueri yang didukung dan tipe tabel dasar bervariasi berdasarkan mode refresh. Dukungan dan batasan Dynamic Table.

Incremental refresh

Incremental refresh mendeteksi perubahan pada tabel dasar dan hanya menulis delta ke Dynamic Table, ideal untuk kueri near-real-time (tingkat menit).

  • Batasan tabel dasar:

    • V3.1 menggunakan mode default stream. Jika tabel dasar Anda memiliki binlog diaktifkan di V3.0, nonaktifkan untuk menghindari biaya penyimpanan tambahan.

    • Di V3.0, Anda harus mengaktifkan binlog untuk tabel dasar, kecuali untuk tabel dimensi yang terlibat dalam join. Mengaktifkan binlog untuk tabel dasar menimbulkan overhead penyimpanan. Periksa penggunaan penyimpanan binlog dengan merujuk ke Lihat detail penyimpanan tabel.

  • Dalam mode incremental refresh, Hologres menghasilkan tabel status di latar belakang untuk mencatat hasil agregasi antara (lihat Dynamic tables untuk detail). Tabel status juga mengonsumsi ruang penyimpanan. Untuk melihat penggunaan penyimpanan, lihat Lihat skema dan lineage dynamic table.

  • Kueri dan operator yang didukung untuk incremental refresh: Dukungan dan batasan Dynamic Table.

  • Ketika Anda menjalankan incremental refresh untuk pertama kali, sistem melakukan pemuatan data penuh dan menginisialisasi tabel status yang digunakan untuk pelacakan status. Karena semua data historis harus diproses sekaligus dan struktur status harus diinisialisasi, konsumsi memori dan sumber daya komputasi jauh lebih tinggi daripada siklus inkremental berikutnya. Jika volume data tabel dasar besar atau sumber daya tidak mencukupi, error kehabisan memori (OOM) dapat terjadi.

  • Untuk menghindari bottleneck sumber daya, evaluasi volume data tabel dasar sebelum menjalankan refresh pertama dan gunakan sumber daya Serverless Computing untuk menjalankannya. Untuk informasi lebih lanjut, lihat Gunakan Serverless Computing untuk pembacaan dan penulisan data.

Join stream-stream

JOIN stream-stream memiliki semantik yang sama dengan kueri OLAP, menggunakan HASH JOIN dan mendukung INNER JOIN, LEFT/RIGHT/FULL OUTER JOIN.

V3.1

Catatan

Mulai dari Hologres V3.1, GUC untuk JOIN stream-stream diaktifkan secara default.

Contoh:

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
);
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt WITH (
  auto_refresh_mode = 'incremental',
  freshness='10 minutes'
) 
AS 
SELECT order_id, orders.user_id, user_name 
FROM orders LEFT JOIN users ON orders.user_id = users.user_id;

-- Setelah refresh, satu catatan yang digabung terlihat
REFRESH TABLE dt;
SELECT * FROM dt;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)


UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- Setelah refresh, dua catatan yang digabung terlihat. Pembaruan tabel dimensi memengaruhi semua data dan dapat memperbaiki catatan yang sebelumnya digabung.
REFRESH TABLE dt;
SELECT * FROM dt;

Hasil:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | dynamic table
        4 |       1 | dynamic table
(2 rows)

V3.0

JOIN stream-stream didukung di V3.0.26. Untuk mengaktifkan fitur ini, tingkatkan instans Anda dan aktifkan GUC:

-- Aktifkan di tingkat session
SET hg_experimental_incremental_dynamic_table_enable_hash_join TO ON;

-- Aktifkan di tingkat DB (berlaku untuk koneksi baru)
ALTER database <db_name> SET hg_experimental_incremental_dynamic_table_enable_hash_join TO ON;

Contoh:

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
) WITH (binlog_level = 'replica');
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt WITH (refresh_mode = 'incremental') 
AS 
SELECT order_id, orders.user_id, user_name 
FROM orders LEFT JOIN users ON orders.user_id = users.user_id;

-- Setelah refresh, satu catatan yang digabung terlihat
REFRESH TABLE dt;
SELECT * FROM dt;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)


UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- Setelah refresh, dua catatan yang digabung terlihat. Pembaruan tabel dimensi memengaruhi semua data dan dapat memperbaiki catatan yang sebelumnya digabung.
REFRESH TABLE dt;
SELECT * FROM dt;

Hasil:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | dynamic table
        4 |       1 | dynamic table
(2 rows)

Join tabel dimensi

Setiap catatan stream digabung dengan snapshot terbaru tabel dimensi pada waktu pemrosesan. Perubahan pada tabel dimensi setelah JOIN tidak memengaruhi data yang sudah diproses.

Catatan

Perilaku JOIN tabel dimensi tidak bergantung pada ukuran tabel; ditentukan oleh pernyataan JOIN.

V3.1

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');

INSERT INTO orders VALUES(1, 1);
CREATE DYNAMIC TABLE dt_join_2 WITH (
    auto_refresh_mode = 'incremental',
    freshness='10 minutes') 
AS 
SELECT order_id, orders.user_id, user_name 
-- FOR SYSTEM_TIME AS OF PROCTIME() mengidentifikasi 'users' sebagai tabel dimensi
FROM orders LEFT JOIN users FOR SYSTEM_TIME AS OF PROCTIME()
ON orders.user_id = users.user_id;

-- Setelah refresh, satu catatan yang digabung terlihat
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;
 order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)


UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- Setelah refresh, dua catatan yang digabung terlihat. Pembaruan tabel dimensi hanya memengaruhi data baru dan tidak dapat memperbaiki data yang sebelumnya digabung.
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

Hasil:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | hologres
        4 |       1 | dynamic table
(2 rows)

V3.0

CREATE TABLE users (
  user_id INT,
  user_name TEXT,
  PRIMARY KEY (user_id)
);
INSERT INTO users VALUES(1, 'hologres');

CREATE TABLE orders (
  order_id INT,
  user_id INT,
  PRIMARY KEY (order_id)
)  WITH (binlog_level = 'replica');
INSERT INTO orders VALUES(1, 1);

CREATE DYNAMIC TABLE dt_join_2 WITH (refresh_mode = 'incremental') 
AS 
SELECT order_id, orders.user_id, user_name 
-- FOR SYSTEM_TIME AS OF PROCTIME() mengidentifikasi 'users' sebagai tabel dimensi
FROM orders LEFT JOIN users FOR SYSTEM_TIME AS OF PROCTIME()
ON orders.user_id = users.user_id;

-- Setelah refresh, satu catatan yang digabung terlihat
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

order_id | user_id | user_name 
----------+---------+-----------
        1 |       1 | hologres
(1 row)
 
UPDATE users SET user_name = 'dynamic table' WHERE user_id = 1;
INSERT INTO orders VALUES(4, 1);

-- Setelah refresh, dua catatan yang digabung terlihat. Pembaruan tabel dimensi hanya memengaruhi data baru dan tidak dapat memperbaiki data yang sebelumnya digabung.
REFRESH TABLE dt_join_2;
SELECT * FROM dt_join_2;

Hasil:

order_id | user_id |   user_name   
----------+---------+---------------
        1 |       1 | hologres
        4 |       1 | dynamic table
(2 rows)

Batasan

Kolom yang diperoleh dari join tabel dimensi bersifat non-deterministik: nilainya bergantung pada baris tabel fakta saat ini dan isi tabel dimensi pada waktu pemrosesan. Dalam hal ini, berperilaku seperti fungsi non-deterministik NOW() dan RAND(). Kami menyarankan Anda hanya menggunakan kolom tersebut dalam daftar proyeksi SELECT. Menggunakannya di tempat lain dapat menyebabkan error refresh atau hasil yang tidak terduga.

Lokasi penggunaan

Diizinkan

SELECT projection list

Ya

Argumen fungsi agregat, seperti SUM(p.price)

Ya, tetapi tidak disarankan. Ketika retraction memicu recomputation, nilai dari tabel dimensi mungkin sudah berubah, yang dapat menghasilkan hasil tak terduga.

GROUP BY kunci

Tidak

Predikat WHERE

Tidak

Kondisi ON dari JOIN hilir

Tidak

Klausa PARTITION BY dari fungsi jendela

Tidak

Jika logika bisnis Anda memerlukan pengelompokan atau penyaringan berdasarkan kolom tabel dimensi, gunakan join stream-stream sebagai gantinya. Perubahan pada tabel dimensi kemudian akan memicu retraction dan recomputation data historis, yang menjaga hasil tetap benar.

Namun, join stream-stream harus mempertahankan status JOIN, sehingga mengonsumsi lebih banyak sumber daya ketika tabel dimensi besar. Perubahan massal pada tabel dimensi juga dapat memicu recomputation hilir yang luas.

Konsumsi inkremental tabel lake Paimon

  • Incremental refresh mendukung konsumsi tabel Paimon untuk skenario lakehouse.

  • Dynamic Table eksternal mendukung pembacaan inkremental dan write-back, mengurangi biaya pemrosesan dan latensi kueri. Pengantar Dynamic Table eksternal.

Konsumsi hibrid

Dynamic Table Inkremental mendukung model hibrid: pemuatan penuh awal dari semua data tabel dasar yang ada, diikuti oleh pemrosesan inkremental berkelanjutan.

V3.1

V3.1 mengaktifkan model refresh hibrid secara default. Contoh:

--Siapkan tabel dasar dan masukkan data
CREATE TABLE base_sales(
  day TEXT NOT NULL,
  hour INT,
  user_id BIGINT,
  ts TIMESTAMPTZ,
  amount FLOAT,
  pk text NOT NULL PRIMARY KEY
);

-- Impor data ke tabel dasar
INSERT INTO base_sales values ('2024-08-29',1,222222,'2024-08-29 16:41:19.141528+08',5,'ddd');


-- Impor lebih banyak data
INSERT INTO base_sales VALUES ('2024-08-29',2,3333,'2024-08-29 17:44:19.141528+08',100,'aaaaa');


-- Buat Dynamic Table Inkremental
CREATE DYNAMIC TABLE sales_incremental
  WITH (
    auto_refresh_mode='incremental',
    freshness='10 minutes'
  ) 
AS 
  SELECT day, hour, SUM(amount), COUNT(1) 
    FROM base_sales 
  GROUP BY day, hour;

Periksa konsistensi data:

  • Kueri tabel dasar

    SELECT day, hour, SUM(amount), COUNT(1) 
        FROM base_sales 
      GROUP BY day, hour;

    Hasil:

    day	    hour	sum	count
    2024-08-29	2	100	1
    2024-08-29	1	5	1
  • Kueri Dynamic Table

    SELECT * FROM sales_incremental;

    Hasil:

    day	    hour	sum	count
    2024-08-29	1	5	1
    2024-08-29	2	100	1

V3.0

Di V3.0, untuk menggunakan konsumsi hibrid, aktifkan secara manual GUC incremental_guc_hg_experimental_enable_hybrid_incremental_mode. Contoh:

--Siapkan tabel dasar, aktifkan Binlog, dan masukkan data
CREATE TABLE base_sales(
  day TEXT NOT NULL,
  hour INT,
  user_id BIGINT,
  ts TIMESTAMPTZ,
  amount FLOAT,
  pk text NOT NULL PRIMARY KEY
);

-- Impor data ke tabel dasar
INSERT INTO base_sales values ('2024-08-29',1,222222,'2024-08-29 16:41:19.141528+08',5,'ddd');

-- Aktifkan Binlog untuk tabel dasar
ALTER TABLE base_sales SET (binlog_level = replica);

-- Impor data inkremental ke tabel dasar
INSERT INTO base_sales VALUES ('2024-08-29',2,3333,'2024-08-29 17:44:19.141528+08',100,'aaaaa');


-- Buat Dynamic Table Inkremental dengan auto-refresh dan aktifkan GUC untuk konsumsi hibrid
CREATE DYNAMIC TABLE sales_incremental
  WITH (
    refresh_mode='incremental',
    incremental_auto_refresh_schd_start_time = 'immediate',
    incremental_auto_refresh_interval = '3 minutes',
    incremental_guc_hg_experimental_enable_hybrid_incremental_mode= 'true'
  ) 
AS 
  SELECT day, hour, SUM(amount), COUNT(1) 
    FROM base_sales 
  GROUP BY day, hour;

Periksa konsistensi data:

  • Kueri tabel dasar

    SELECT day, hour, SUM(amount), COUNT(1) 
        FROM base_sales 
      GROUP BY day, hour;

    Hasil:

    day	    hour	sum	count
    2024-08-29	2	100	1
    2024-08-29	1	5	1
  • Kueri Dynamic Table

    SELECT * FROM sales_incremental;

    Hasil:

    day	    hour	sum	count
    2024-08-29	1	5	1
    2024-08-29	2	100	1

Full refresh

Full refresh menulis ulang seluruh dataset dari kueri. Dibandingkan dengan incremental refresh:

  • Mendukung lebih banyak tipe tabel dasar.

  • Mendukung lebih banyak tipe kueri dan operator.

Full refresh menggunakan lebih banyak sumber daya. Paling cocok untuk pelaporan periodik dan pengisian ulang data.

Catatan

Untuk informasi lebih lanjut, lihat Full refresh.

Contoh

V3.1

Contoh 1: Membuat Incremental Dynamic Table reguler

Sebelum melanjutkan, impor dataset publik tpch_10g ke Hologres dengan mengikuti panduan di Impor dataset publik dengan beberapa klik.

Catatan

Sebelum membuat Incremental Dynamic Table, aktifkan Binlog untuk tabel dasar (tidak diperlukan untuk tabel dimensi).

-- Buat Incremental Dynamic Table yang merefresh setiap 3 menit.
CREATE DYNAMIC TABLE public.tpch_q1_incremental 
WITH (
auto_refresh_mode='incremental',
freshness='3 minutes'
) AS SELECT
        l_returnflag,
        l_linestatus,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus;

Contoh 2: Buat Incremental Dynamic Table dari join stream-stream

Sebelum melanjutkan, impor dataset publik tpch_10g ke Hologres dengan mengikuti panduan di Impor dataset publik dengan beberapa klik.

Catatan

Sebelum membuat Incremental Dynamic Table, aktifkan binlog untuk tabel dasar (tidak diperlukan untuk tabel dimensi).

-- Buat Incremental Dynamic Table dari join stream-stream.
CREATE DYNAMIC TABLE dt_join
  WITH (
    auto_refresh_mode='incremental',
    freshness='30 minutes'
  ) 
AS 
SELECT
        l_shipmode,
        SUM(CASE
                WHEN o_orderpriority = '1-URGENT'
                        OR o_orderpriority = '2-HIGH'
                        THEN 1
                ELSE 0
        END) AS high_line_count,
        SUM(CASE
                WHEN o_orderpriority <> '1-URGENT'
                        AND o_orderpriority <> '2-HIGH'
                        THEN 1
                ELSE 0
        END) AS low_line_count
FROM
        hologres_dataset_tpch_10g.orders,
        hologres_dataset_tpch_10g.lineitem
WHERE
        o_orderkey = l_orderkey
        AND l_shipmode IN ('FOB', 'AIR')
        AND l_commitdate < l_receiptdate
        AND l_shipdate < l_commitdate
        AND l_receiptdate >= DATE '1997-01-01'
        AND l_receiptdate < DATE '1997-01-01' + INTERVAL '1' YEAR
GROUP BY
        l_shipmode;

Contoh 3: Buat Dynamic Table dengan auto-refresh

Atur mode refresh ke auto. Mesin memprioritaskan incremental refresh dan beralih ke full refresh jika tidak didukung.

Sebelum melanjutkan, impor dataset publik tpch_10g ke Hologres dengan mengikuti panduan di Impor dataset publik dengan beberapa klik.

-- Buat Dynamic Table Auto-refresh yang secara cerdas menentukan mode refresh. Dalam contoh ini, hasilnya adalah incremental refresh.
CREATE DYNAMIC TABLE thch_q6_auto
  WITH (
    auto_refresh_mode='auto',
    freshness='1 hours'
       ) 
AS
SELECT
        SUM(l_extendedprice * l_discount) AS revenue
FROM
        hologres_dataset_tpch_100g.lineitem
WHERE
        l_shipdate >= DATE '1996-01-01'
        AND l_shipdate < DATE '1996-01-01' + INTERVAL '1' YEAR
        AND l_discount BETWEEN 0.02 - 0.01 AND 0.02 + 0.01
        AND l_quantity < 24;

Contoh 4: Buat Dynamic Table partisi logis

Untuk dasbor transaksi real-time, seringkali diperlukan tampilan near-real-time data saat ini dan koreksi data historis, yang memerlukan solusi analisis real-time dan offline terintegrasi (Kognisi bisnis dan data). Pendekatan umum menggunakan partisi logis `Dynamic Table` untuk skenario ini adalah sebagai berikut:

  • Tabel dasar dipartisi berdasarkan hari. Partisi terbaru ditulis oleh Flink secara real-time/near-real-time, sedangkan partisi historis ditulis dari MaxCompute.

  • Dynamic Table dibuat sebagai tabel partisi logis. Dua partisi terbaru aktif dan direfresh secara inkremental untuk analitik data near-real-time.

  • Partisi historis tidak aktif dan menggunakan full refresh. Jika partisi historis tabel dasar telah dikoreksi atau diisi ulang, partisi tersebut dapat direfresh menggunakan full refresh.

Contoh ini menggunakan dataset publik dari GitHub.

  1. Siapkan tabel dasar.

    Gunakan Flink untuk menulis data terbaru ke tabel dasar. Untuk langkah-langkah detail, lihat Analitik batch dan real-time terpadu pada event GitHub.

    DROP TABLE IF EXISTS gh_realtime_data;
    
    BEGIN;
    CREATE TABLE gh_realtime_data (
        id BIGINT,
        actor_id BIGINT,
        actor_login TEXT,
        repo_id BIGINT,
        repo_name TEXT,
        org_id BIGINT,
        org_login TEXT,
        type TEXT,
        created_at timestamp with time zone NOT NULL,
        action TEXT,
        iss_or_pr_id BIGINT,
        number BIGINT,
        comment_id BIGINT,
        commit_id TEXT,
        member_id BIGINT,
        rev_or_push_or_rel_id BIGINT,
        ref TEXT,
        ref_type TEXT,
        state TEXT,
        author_association TEXT,
        language TEXT,
        merged BOOLEAN,
        merged_at TIMESTAMP WITH TIME ZONE,
        additions BIGINT,
        deletions BIGINT,
        changed_files BIGINT,
        push_size BIGINT,
        push_distinct_size BIGINT,
        hr TEXT,
        month TEXT,
        year TEXT,
        ds TEXT,
        PRIMARY KEY (id,ds)
    )
    PARTITION BY LIST (ds);
    CALL set_table_property('public.gh_realtime_data', 'distribution_key', 'id');
    CALL set_table_property('public.gh_realtime_data', 'event_time_column', 'created_at');
    CALL set_table_property('public.gh_realtime_data', 'clustering_key', 'created_at');
    
    COMMENT ON COLUMN public.gh_realtime_data.id IS 'Event ID';
    COMMENT ON COLUMN public.gh_realtime_data.actor_id IS 'Event actor ID';
    COMMENT ON COLUMN public.gh_realtime_data.actor_login IS 'Event actor login name';
    COMMENT ON COLUMN public.gh_realtime_data.repo_id IS 'Repo ID';
    COMMENT ON COLUMN public.gh_realtime_data.repo_name IS 'Repo name';
    COMMENT ON COLUMN public.gh_realtime_data.org_id IS 'Repo organization ID';
    COMMENT ON COLUMN public.gh_realtime_data.org_login IS 'Repo organization name';
    COMMENT ON COLUMN public.gh_realtime_data.type IS 'Event type';
    COMMENT ON COLUMN public.gh_realtime_data.created_at IS 'Event time';
    COMMENT ON COLUMN public.gh_realtime_data.action IS 'Event action';
    COMMENT ON COLUMN public.gh_realtime_data.iss_or_pr_id IS 'Issue/pull_request ID';
    COMMENT ON COLUMN public.gh_realtime_data.number IS 'Issue/pull_request number';
    COMMENT ON COLUMN public.gh_realtime_data.comment_id IS 'Comment ID';
    COMMENT ON COLUMN public.gh_realtime_data.commit_id IS 'Commit ID';
    COMMENT ON COLUMN public.gh_realtime_data.member_id IS 'Member ID';
    COMMENT ON COLUMN public.gh_realtime_data.rev_or_push_or_rel_id IS 'Review/push/release ID';
    COMMENT ON COLUMN public.gh_realtime_data.ref IS 'Name of created/deleted resource';
    COMMENT ON COLUMN public.gh_realtime_data.ref_type IS 'Type of created/deleted resource';
    COMMENT ON COLUMN public.gh_realtime_data.state IS 'State of issue/pull_request/pull_request_review';
    COMMENT ON COLUMN public.gh_realtime_data.author_association IS 'Relationship between actor and repo';
    COMMENT ON COLUMN public.gh_realtime_data.language IS 'Programming language';
    COMMENT ON COLUMN public.gh_realtime_data.merged IS 'Whether merged';
    COMMENT ON COLUMN public.gh_realtime_data.merged_at IS 'Merge time';
    COMMENT ON COLUMN public.gh_realtime_data.additions IS 'Number of added lines';
    COMMENT ON COLUMN public.gh_realtime_data.deletions IS 'Number of deleted lines';
    COMMENT ON COLUMN public.gh_realtime_data.changed_files IS 'Number of changed files in pull request';
    COMMENT ON COLUMN public.gh_realtime_data.push_size IS 'Number of pushes';
    COMMENT ON COLUMN public.gh_realtime_data.push_distinct_size IS 'Number of distinct pushes';
    COMMENT ON COLUMN public.gh_realtime_data.hr IS 'Hour of event, e.g., 00 for 00:23';
    COMMENT ON COLUMN public.gh_realtime_data.month IS 'Month of event, e.g., 2015-10 for Oct 2015';
    COMMENT ON COLUMN public.gh_realtime_data.year IS 'Year of event, e.g., 2015';
    COMMENT ON COLUMN public.gh_realtime_data.ds IS 'Date of event, ds=yyyy-mm-dd';
    
    COMMIT;
  2. Buat Dynamic Table partisi logis.

    CREATE  DYNAMIC TABLE ads_dt_github_event
    LOGICAL PARTITION BY LIST(ds)
    WITH (
      -- Properti dynamic table
      freshness = '5 minutes', 
      auto_refresh_mode = 'auto', 
      auto_refresh_partition_active_time = '2 days' ,
      partition_key_time_format = 'YYYY-MM-DD'
    )
    AS
    SELECT
        repo_name,
        COUNT(*) AS events,
        ds
    FROM
        gh_realtime_data
    GROUP BY repo_name,ds
  3. Kueri Dynamic Table.

    SELECT * FROM ads_dt_github_event ;
  4. Isi ulang partisi historis.

    Jika data historis di tabel dasar berubah (misalnya, data untuk '2025-04-01'), dan Dynamic Table perlu diperbarui, atur partisi historis ke mode full refresh dan picu refresh, sebaiknya dengan sumber daya Serverless Computing.

    REFRESH OVERWRITE DYNAMIC TABLE ads_dt_github_event
    PARTITION (ds = '2025-04-01') 
    WITH (
      refresh_mode = 'full'
    );

Contoh 5: Hitung UV dengan Incremental Dynamic Table

Mulai dari Hologres V3.1, Incremental Dynamic Table mendukung fungsi RB_BUILD_AGG untuk perhitungan seperti jumlah UV. Dibandingkan dengan pre-agregasi, pendekatan ini menawarkan:

  • Performa lebih cepat: Hanya menghitung data inkremental.

  • Biaya lebih rendah: Volume data dan penggunaan sumber daya berkurang, memungkinkan perhitungan periode lebih panjang.

Contoh:

  1. Siapkan tabel detail pengguna.

    BEGIN;
    CREATE TABLE IF NOT EXISTS ods_app_detail (
         uid INT,
         country TEXT,
         prov TEXT,
         city TEXT,
         channel TEXT,
         operator TEXT,
         brand TEXT,
         ip TEXT,
         click_time TEXT,
         year TEXT,
         month TEXT,
         day TEXT,
         ymd TEXT NOT NULL
    );
    CALL set_table_property('ods_app_detail', 'orientation', 'column');
    CALL set_table_property('ods_app_detail', 'bitmap_columns', 'country,prov,city,channel,operator,brand,ip,click_time, year, month, day, ymd');
    -- Atur distribution_key berdasarkan kebutuhan kueri untuk efek sharding optimal.
    CALL set_table_property('ods_app_detail', 'distribution_key', 'uid');
    -- Untuk bidang dengan tanggal-waktu lengkap yang digunakan dalam filter WHERE, disarankan mengaturnya sebagai clustering_key dan event_time_column.
    CALL set_table_property('ods_app_detail', 'clustering_key', 'ymd');
    CALL set_table_property('ods_app_detail', 'event_time_column', 'ymd');
    COMMIT;
  2. Hitung UV menggunakan Incremental Dynamic Table.

    CREATE DYNAMIC TABLE ads_uv_dt
      WITH (
        freshness = '5 minutes', 
        auto_refresh_mode = 'incremental') 
      AS 
    SELECT  
     RB_BUILD_AGG(uid),
     country,
     prov,
     city,
     ymd,
    COUNT(1)
    FROM    ods_app_detail
    WHERE ymd >= '20231201' AND ymd <='20240502'
    GROUP BY country,prov,city,ymd;
  3. Kueri UV untuk hari tertentu.

    SELECT  
    RB_CARDINALITY(RB_OR_AGG(rb_uid)) AS uv,
      country,
      prov,
      city,
      SUM(pv) AS pv
    FROM    ads_uv_dt
    WHERE   ymd = '20240329'
    GROUP BY country,prov,city;

V3.0

Contoh 1: Buat dynamic table full-refresh yang mulai otomatis

Sebelum melanjutkan, impor dataset publik tpch_10g ke Hologres dengan mengikuti panduan di Impor dataset publik dengan beberapa klik.

--Buat Skema "test"
CREATE SCHEMA test;

--Buat dynamic table single-table full refresh, mulai segera dan merefresh setiap jam.
CREATE DYNAMIC TABLE test.thch_q1_full
  WITH (
    refresh_mode='full',
    auto_refresh_enable='true',
    full_auto_refresh_interval='1 hours',
    full_guc_hg_computing_resource='serverless',
    full_guc_hg_experimental_serverless_computing_required_cores='32'
       ) 
AS
  SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus;

Contoh 2: Buat dynamic table inkremental dengan waktu mulai

Sebelum melanjutkan, impor dataset publik tpch_10g ke Hologres dengan mengikuti panduan di Impor dataset publik dengan beberapa klik.

Contoh:

Catatan

Sebelum membuat `Dynamic Table` inkremental, Anda harus mengaktifkan Binlog untuk tabel dasar (tidak diperlukan untuk tabel dimensi).

--Aktifkan binlog untuk tabel dasar:
BEGIN;
CALL set_table_property('hologres_dataset_tpch_10g.lineitem', 'binlog.level', 'replica');
COMMIT;

--Buat dynamic table single-table incremental refresh, menentukan waktu mulai dan interval refresh 3 menit.
CREATE DYNAMIC TABLE public.tpch_q1_incremental 
WITH (
refresh_mode='incremental',
auto_refresh_enable='true',
incremental_auto_refresh_schd_start_time='2024-09-15 23:50:0',
incremental_auto_refresh_interval='3 minutes',
incremental_guc_hg_computing_resource='serverless',
incremental_guc_hg_experimental_serverless_computing_required_cores='30'
) AS SELECT
        l_returnflag,
        l_linestatus,
        COUNT(*) AS count_order
FROM
        hologres_dataset_tpch_10g.lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus
;

Contoh 3: Buat dynamic table full-refresh multi-join

--Buat dynamic table dengan kueri join multi-tabel, menggunakan mode full refresh setiap 3 jam.
CREATE DYNAMIC TABLE dt_q_full
  WITH (
    refresh_mode='full',
    auto_refresh_enable='true',
    full_auto_refresh_schd_start_time='immediate',
    full_auto_refresh_interval='3 hours',
    full_guc_hg_computing_resource='serverless',
    full_guc_hg_experimental_serverless_computing_required_cores='64'
  ) 
AS 
SELECT
        o_orderpriority,
        COUNT(*) AS order_count
FROM
        hologres_dataset_tpch_10g.orders
WHERE
        o_orderdate >= DATE '1996-07-01'
        AND o_orderdate < DATE '1996-07-01' + INTERVAL '3' MONTH
        AND EXISTS (
                SELECT
                        *
                FROM
                        hologres_dataset_tpch_10g.lineitem
                WHERE
                        l_orderkey = o_orderkey
                        AND l_commitdate < l_receiptdate
        )
GROUP BY
        o_orderpriority;

Contoh 4: Buat dynamic table inkremental join dimensi

Contoh:

Catatan

Sebelum membuat `Dynamic Table` inkremental, Anda harus mengaktifkan Binlog untuk tabel dasar (tidak diperlukan untuk tabel dimensi).

Semantik JOIN tabel dimensi adalah bahwa setiap catatan hanya digabung dengan versi terbaru data tabel dimensi pada waktu tersebut, yaitu JOIN terjadi pada waktu pemrosesan. Jika data tabel dimensi berubah (tambah, perbarui, atau hapus) setelah JOIN, data yang sudah digabung tidak diperbarui. Contoh SQL:

--Tabel detail
BEGIN;
CREATE TABLE public.sale_detail(
        app_id TEXT,
        uid TEXT,
        product TEXT,
        gmv BIGINT,
        order_time TIMESTAMPTZ
);
--Aktifkan binlog untuk tabel dasar; tabel dimensi tidak memerlukannya.
CALL set_table_property('public.sale_detail', 'binlog.level', 'replica');
COMMIT;

--Tabel properti
CREATE TABLE public.user_info(
        uid TEXT,
        province TEXT,
        city TEXT
);

CREATE DYNAMIC TABLE public.dt_sales_incremental
  WITH (
    refresh_mode='incremental',
    auto_refresh_enable='true',
    incremental_auto_refresh_schd_start_time='2024-09-15 00:00:00',
    incremental_auto_refresh_interval='5 minutes',
    incremental_guc_hg_computing_resource='serverless',
    incremental_guc_hg_experimental_serverless_computing_required_cores='128') 
AS 
SELECT 
    sale_detail.app_id,
    sale_detail.uid,
    product,
    SUM(sale_detail.gmv) AS sum_gmv,
    sale_detail.order_time,
    user_info.province,
    user_info.city 
FROM public.sale_detail 
INNER JOIN public.user_info  FOR SYSTEM_TIME AS OF PROCTIME()
ON sale_detail.uid =user_info.uid
GROUP BY sale_detail.app_id,sale_detail.uid,sale_detail.product,sale_detail.order_time,user_info.province,user_info.city;

Contoh 5: Buat dynamic table partisi

Untuk dasbor transaksi real-time, seringkali diperlukan tampilan near-real-time data saat ini dan koreksi data historis. Hal ini dapat dicapai dengan kombinasi `Dynamic Table` incremental dan full refresh. Pendekatannya sebagai berikut:

  1. Buat tabel dasar partisi di mana partisi terbaru ditulis secara real-time/near-real-time, dan partisi historis kadang-kadang dikoreksi.

  2. Buat `Dynamic Table` sebagai tabel induk partisi. Gunakan incremental refresh untuk partisi terbaru untuk memenuhi kebutuhan analisis near-real-time.

  3. Alihkan partisi historis ke mode full refresh. Jika partisi historis tabel sumber telah dikoreksi, partisi `Dynamic Table` juga dapat diisi ulang menggunakan full refresh, sebaiknya dengan Serverless untuk mempercepatnya.

Contoh:

  1. Siapkan tabel dasar dan data.

    Tabel dasar adalah tabel partisi, dengan partisi terbaru menerima data real-time.

    -- Buat tabel sumber partisi
    CREATE TABLE base_sales(
      uid INT,
      opreate_time TIMESTAMPTZ,
      amount FLOAT,
      tt TEXT NOT NULL,
      ds TEXT,
      PRIMARY KEY(ds)
    ) PARTITION BY LIST (ds) ;
    
    --Partisi historis
    CREATE TABLE base_sales_20240615 PARTITION OF base_sales FOR VALUES IN ('20240615');
    INSERT INTO base_sales_20240615 VALUES (2,'2024-06-15 16:18:25.387466+08','111','2','20240615');
    
    --Partisi terbaru, biasanya untuk penulisan real-time
    CREATE TABLE base_sales_20240616 PARTITION OF base_sales FOR VALUES IN ('20240616');
    INSERT INTO base_sales_20240616 VALUES (1,'2024-06-16 16:08:25.387466+08','2','1','20240616');

  2. Buat tabel induk `Dynamic Table` partisi, hanya mendefinisikan kueri tanpa mode refresh.

    --Buat ekstensi
    CREATE EXTENSION roaringbitmap;
    
    CREATE DYNAMIC TABLE partition_dt_base_sales
    PARTITION BY LIST (ds)
    as
    SELECT  
     public.RB_BUILD_AGG(uid),
     opreate_time,
     amount,
     tt,
     ds,
    COUNT(1)
    FROM    base_sales
    GROUP BY opreate_time ,amount,tt,ds;

  3. Buat sub-tabel dan atur mode refresh-nya.

    Anda dapat membuat sub-partisi `Dynamic Table` secara manual atau dinamis menggunakan DataWorks. Atur partisi terbaru ke incremental refresh dan partisi historis ke full refresh.

    -- Aktifkan Binlog untuk tabel dasar
    ALTER TABLE base_sales SET (binlog_level = replica);
    
    -- Asumsikan sub-partisi Dynamic Table historis adalah sebagai berikut:
    CREATE DYNAMIC TABLE partition_dt_base_sales_20240615 PARTITION OF partition_dt_base_sales FOR VALUES IN ('20240615')
      WITH (
        refresh_mode='incremental',
        auto_refresh_enable='true',
        incremental_auto_refresh_schd_start_time='immediate',
        incremental_auto_refresh_interval='30 minutes'
           );
    
    -- Buat sub-partisi Dynamic Table baru, atur mode refresh-nya ke incremental, mulai segera, refresh setiap 30 menit, dan gunakan sumber daya instans.
    CREATE DYNAMIC TABLE partition_dt_base_sales_20240616 PARTITION OF partition_dt_base_sales FOR VALUES IN ('20240616')
      WITH (
        refresh_mode='incremental',
        auto_refresh_enable='true',
        incremental_auto_refresh_schd_start_time='immediate',
        incremental_auto_refresh_interval='30 minutes'
           );
    
    --Alihkan partisi historis ke mode full refresh
    ALTER DYNAMIC TABLE partition_dt_base_sales_20240615 SET (refresh_mode = 'full');
    --Jika data partisi historis perlu dikoreksi, jalankan refresh, sebaiknya dengan serverless.
    SET hg_computing_resource = 'serverless';
    REFRESH DYNAMIC TABLE partition_dt_base_sales_20240615;

Konversi sintaks lama ke sintaks baru

Hologres V3.1 mengubah sintaks pembuatan Dynamic Table. Setelah meningkatkan dari V3.0, buat ulang Dynamic Table dengan sintaks baru. Alat konversi menyederhanakan proses ini.

Skenario

  • Incremental Dynamic Table harus dibuat ulang dengan sintaks baru.

  • Ketidakcocokan sintaks ditemukan selama pemeriksaan peningkatan. Rujuk laporan pemeriksaan peningkatan Anda untuk detailnya.

Catatan

Kecuali untuk skenario di atas, Dynamic Table dari V3.0 tidak perlu dibuat ulang di Hologres V3.1. Namun, hanya ALTER DYNAMIC TABLE yang dapat dilakukan pada mereka. CREATE DYNAMIC TABLE (sintaks lama) tidak didukung di V3.1+.

Batasan

Perintah konversi sintaks terbatas pada tabel non-partisi (baik Incremental maupun Full-refresh). Untuk Dynamic Table partisi dari V3.0, buat ulang secara manual.

Lihat Dynamic Table yang memerlukan konversi sintaks

Temukan tabel di instans Anda yang perlu dikonversi setelah peningkatan:

Tabel non-partisi

SELECT DISTINCT 
    p.dynamic_table_namespace as table_namespace, 
    p.dynamic_table_name as table_name
FROM hologres.hg_dynamic_table_properties p
JOIN pg_class c ON c.relname = p.dynamic_table_name
JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = p.dynamic_table_namespace
WHERE p.property_key = 'refresh_mode' 
    AND p.property_value = 'incremental'
    AND c.relispartition = false 
    AND c.relkind != 'p';

Tabel partisi

SELECT DISTINCT 
    pn.nspname as parent_schema,
    pc.relname as parent_name
FROM hologres.hg_dynamic_table_properties p
JOIN pg_class c ON c.relname = p.dynamic_table_name
JOIN pg_namespace n ON n.oid = c.relnamespace AND n.nspname = p.dynamic_table_namespace
JOIN pg_inherits i ON c.oid = i.inhrelid
JOIN pg_class pc ON pc.oid = i.inhparent
JOIN pg_namespace pn ON pn.oid = pc.relnamespace
WHERE p.property_key = 'refresh_mode' 
    AND p.property_value = 'incremental'
    AND c.relispartition = true 
    AND c.relkind != 'p';

Lakukan konversi sintaks

Catatan:

  • Persyaratan versi: V3.1.11 dan versi lebih baru.

  • Persyaratan peran: Superuser.

  • Perubahan perilaku pasca-konversi:

    • Refresh otomatis dimulai segera jika mode refresh adalah auto. Pastikan operasi dilakukan selama jam sepi untuk menghindari konflik sumber daya. Untuk isolasi yang lebih baik, gunakan sumber daya Serverless Computing.

    • Perubahan penggunaan sumber daya untuk instans gudang virtual:

      • V3.1/V3.2 (sintaks baru): Refresh Dynamic Table menggunakan sumber daya dari gudang virtual utama dari Kelompok Tabel tabel dasar dan dynamic table.

      • V3.0 (sintaks lama) dan V4.1 (sintaks baru): Refresh Dynamic Table menggunakan sumber daya dari gudang virtual utama dari Kelompok Tabel Dynamic Table.

    • Sintaks baru menambahkan satu koneksi per Dynamic Table untuk penjadwalan. Jika instans Anda memiliki penggunaan koneksi tinggi, bersihkan koneksi idle terlebih dahulu.

Perintah:

-- Hanya untuk tabel non-partisi (full dan incremental).
-- Konversi satu Dynamic Table
call hg_dynamic_table_config_upgrade('<table_name>');

-- Konversi semua Dynamic Table. Gunakan dengan hati-hati.
call hg_upgrade_all_normal_dynamic_tables();
Catatan

Perintah ini mengonversi Dynamic Table (sintaks lama) di database saat ini ke sintaks baru.

Pemetaan parameter sintaks

Perintah memetakan parameter dan nilai V3.0 dan V3.1 sebagai berikut:

Sintaks lama (V3.0)

Sintaks baru (V3.1+)

Deskripsi

refresh_mode

auto_refresh_mode

Nilai parameter dipertahankan setelah konversi. Misalnya, refresh_mode='incremental' menjadi auto_refresh_mode='incremental'.

auto_refresh_enable

auto_refresh_enable

Nilai parameter dipertahankan setelah konversi.

{refresh_mode}_auto_refresh_schd_start_time

freshness

Nilai auto_refresh_interval menjadi nilai freshness.

Misalnya, full_auto_refresh_interval='30 minutes' menjadi freshness='30 minutes'.

{refresh_mode}_auto_refresh_interval

{refresh_mode}_guc_hg_computing_resource

computing_resource

Nilai parameter dipertahankan setelah konversi. Misalnya, full_guc_hg_computing_resource='serverless' menjadi computing_resource='serverless'.

{refresh_mode}guc_hg_experimental_serverless_computing_required_cores

refresh_guc_hg_experimental_serverless_computing_required_cores

Nilai parameter dipertahankan setelah konversi.

{refresh_mode}guc<guc>

refresh_guc<guc_name>

Nilai parameter dipertahankan setelah konversi. Misalnya, incremental_guc_hg_experimental_max_consumed_rows_per_refresh='1000000' menjadi refresh_guc_hg_experimental_max_consumed_rows_per_refresh='1000000'.

Properti tabel (misalnya, orientation)

Properti tabel (misalnya, orientation)

Properti tabel dasar tetap tidak berubah.

Referensi

FAQ

  • T: Bagaimana cara memperbaiki error dengan kunci segmen atau pengelompokan null? Contoh:

    ERROR: commit ddl phase1 failed: the index partition key "xxx" should not be nullable
  • Penyebab: Kunci segmen atau pengelompokan Dynamic Table tidak boleh null. Untuk aturan pengaturan kunci ini, lihat Kolom waktu event (kunci segmen).

  • Solusi:

    1. Error kunci pengelompokan: Untuk Hologres sebelum V3.1.26, V3.2.9, V4.0.0, tingkatkan instans Anda dan modifikasi GUC berikut untuk mengizinkan kunci pengelompokan yang dapat null:

      -- Untuk V3.1 dan versi lebih baru
      ALTER DYNAMIC TABLE [ IF EXISTS ] [<schema>.]<table_name> SET
      (refresh_guc_hg_experimental_enable_nullable_segment_key=true);
    2. Error kunci segmen: Jalankan perintah berikut untuk mengizinkan kunci segmen yang dapat null. Mulai dari Hologres V4.1, kunci segmen secara default diizinkan null, jadi kami menyarankan untuk meningkatkan instans Anda untuk memperbaiki error.

      --Untuk V3.1 dan versi lebih baru, mengizinkan kunci pengelompokan yang dapat null
      ALTER DYNAMIC TABLE [ IF EXISTS ] [<schema>.]<table_name> SET
      (refresh_guc_hg_experimental_enable_nullable_clustering_key=true);