Pelajari cara menyetel kueri tabel internal Hologres dengan memelihara statistik, mengonfigurasi shard, mengoptimalkan penggabungan tabel (join) dan agregasi, serta merancang skema tabel yang efisien.
Panduan keputusan cepat
|
Gejala |
Kemungkinan penyebab |
Aksi yang direkomendasikan |
|
Join lambat pada tabel internal berukuran besar |
Statistik usang |
Jalankan ANALYZE pada semua tabel yang terlibat dalam join |
|
Kueri memindai terlalu banyak baris untuk filter rentang atau kesamaan |
Tidak ada clustering key, kolom bitmap, atau segment key |
Tambahkan clustering_key untuk filter rentang, bitmap_columns untuk filter kesamaan, atau segment_key untuk rentang berbasis waktu |
|
Latensi tinggi untuk kueri titik (point queries) |
Tipe penyimpanan tidak sesuai atau tidak ada primary key/indeks |
Gunakan penyimpanan row atau hybrid dan definisikan primary key serta indeks yang sesuai |
|
Agregasi COUNT DISTINCT lambat |
Deduplikasi eksak yang intensif sumber daya |
Gunakan APPROX_COUNT_DISTINCT atau UNIQ, dan pertimbangkan menggunakan distinct key sebagai distribution key |
|
Agregasi GROUP BY lambat |
Redistribusi data dan data skew pada kunci GROUP BY |
Tetapkan kunci GROUP BY sebagai distribution key jika memungkinkan dan perbaiki data skew |
Memelihara statistik
Statistik (misalnya, distribusi data, jumlah baris, kolom) membantu pengoptimal memilih rencana eksekusi yang efisien. Statistik yang usang dapat menyebabkan pemilihan urutan join yang buruk dan error OOM.
Periksa apakah statistik terkini
Jalankan EXPLAIN pada kueri Anda dan periksa estimasi rows untuk setiap tabel.
Jika tabel besar menunjukkan rows=1000 (nilai default), statistik tersebut sudah usang.
Perbarui statistik
Jalankan ANALYZE pada tabel dengan statistik usang:
analyze <tablename>;
Identifikasi kapan harus memperbarui statistik
Jalankan analyze <tablename> saat:
-
Setelah mengimpor data.
-
Setelah beberapa operasi INSERT, UPDATE, atau DELETE.
-
Untuk tabel internal maupun tabel eksternal.
-
Pada tabel induk untuk tabel partisi.
Jika Anda mengalami error OOM selama join atau kueri lambat, jalankan analyze <tablename> sebelum mengimpor data.
Mengonfigurasi jumlah shard
Jumlah shard menentukan paralelisme kueri. Terlalu sedikit shard membatasi paralelisme; terlalu banyak meningkatkan overhead startup.
Pahami jumlah shard default
Hologres menetapkan jumlah shard default berdasarkan spesifikasi instans, kira-kira sama dengan jumlah CU kueri yang tersedia. Setelah penskalaan, database yang sudah ada mempertahankan jumlah shard aslinya—hanya database baru yang menggunakan nilai default yang diperbarui.
Tentukan kapan harus menyesuaikan jumlah shard
-
Setelah penskalaan naik 5x atau lebih: Buat Table Group baru dengan jumlah shard yang lebih besar.
-
Untuk workload bisnis baru: Buat Table Group baru dengan jumlah shard yang sesuai.
-
Saat mengalami masalah paralelisme: Periksa apakah total shard melebihi nilai default yang direkomendasikan.
Total shard di seluruh Table Group sebaiknya tidak melebihi jumlah shard default instans agar pemanfaatan CPU optimal.
Mengoptimalkan kueri JOIN
Gunakan metode berikut untuk meningkatkan kinerja join.
Perbarui statistik untuk kueri join
Seperti disebutkan dalam Memelihara statistik, statistik yang usang dapat menyebabkan tabel yang lebih besar membuat hash table, sehingga mengurangi efisiensi join. Jalankan ANALYZE untuk memperbarui statistik tabel.
Pilih distribution key untuk join lokal
Distribution key menentukan bagaimana data didistribusikan ke seluruh shard. Pemilihan yang tepat memungkinkan join lokal dan mengurangi pengacakan data (data shuffling).
Prinsip pemilihan distribution key:
-
Gunakan kolom join sebagai distribution key.
-
Gunakan kolom dalam klausa GROUP BY yang sering digunakan.
-
Pilih kolom dengan distribusi data yang merata dan diskret.
Contoh: Saat melakukan join tabel secara rutin pada kolom tertentu, tetapkan kolom tersebut sebagai distribution key untuk kedua tabel:
-- Buat tabel dengan distribution key yang cocok
BEGIN;
CREATE TABLE orders (order_id INT, customer_id INT, amount DECIMAL);
CALL set_table_property('orders', 'distribution_key', 'customer_id');
COMMIT;
BEGIN;
CREATE TABLE customers (id INT, name TEXT);
CALL set_table_property('customers', 'distribution_key', 'id');
COMMIT;
Dengan distribution key yang benar, rencana eksekusi tidak menampilkan operator Redistribute Motion, yang mengonfirmasi join lokal.
Gunakan Runtime Filter dalam join
Sejak V2.0, Hologres secara otomatis menerapkan Percepat join multi-tabel dengan runtime filter untuk join tabel besar-kecil, sehingga mengurangi data yang dipindai tanpa konfigurasi manual.
Menyetel algoritma urutan join
Untuk kueri yang menggabungkan banyak tabel, pengoptimal mungkin memerlukan waktu terlalu lama untuk menemukan urutan join optimal. Sesuaikan algoritma sesuai kebutuhan:
set optimizer_join_order = '<value>';
|
Algoritma |
Kasus penggunaan |
Trade-off |
|
exhaustive2 |
Default untuk sebagian besar kueri |
Rencana terbaik, biaya optimasi tertinggi |
|
greedy |
Lebih dari 10 tabel |
Optimasi lebih cepat, rencana berpotensi suboptimal |
|
query |
SQL sederhana dengan urutan jelas |
Dieksekusi sesuai urutan SQL, biaya optimasi terendah |
Mengoptimalkan operator Motion dalam join
Hologres menggunakan operator Motion untuk mendistribusikan ulang data antar shard:
|
Jenis Motion |
Deskripsi |
|
Redistribute Motion |
Mengacak data berdasarkan hash atau acak |
|
Broadcast Motion |
Menyalin data ke semua shard. |
|
Gather Motion |
Mengumpulkan data ke satu shard. |
|
Forward Motion |
Memindahkan data antara sumber eksternal dan Hologres untuk kueri federasi. |
Periksa rencana eksekusi untuk operator Motion yang mahal dan sesuaikan desain tabel:
-
Operator Motion yang memakan waktu: Rancang ulang distribusi.
-
Karakteristik Motion tidak efisien akibat statistik usang: Segarkan statistik dengan
analyze. -
Membroadcast tabel kecil: Kurangi jumlah shard untuk mengoptimalkan efisiensi Broadcast Motion.
Mengoptimalkan agregasi
Mengoptimalkan COUNT DISTINCT
-
Ganti COUNT DISTINCT eksak (intensif sumber daya) dengan APPROX_COUNT_DISTINCT (lebih cepat, tingkat error 0,1% hingga 1%) bila variasi kecil dapat diterima.
-
Ganti COUNT DISTINCT dengan UNIQ (V1.3+).
-
Tetapkan distribution key yang sesuai
Gunakan kunci COUNT DISTINCT sebagai distribution key untuk menghindari pengacakan data antar shard.
-
Upgrade ke V2.1+ untuk optimasi bawaan
V2.1+ mencakup optimasi bawaan untuk skenario COUNT DISTINCT termasuk satu atau lebih COUNT DISTINCT, data skew, dan kueri tanpa GROUP BY.
Paksa agregasi multi-tahap
Agregasi multi-tahap mengurangi transfer data dengan melakukan agregasi parsial di setiap shard terlebih dahulu:
set optimizer_force_multistage_agg = on;Mengoptimalkan beberapa fungsi agregat pada kolom yang sama
Sejak V4.0, Hologres secara otomatis mendeduplikasi fungsi agregat identik pada kolom yang sama, sehingga mengurangi komputasi. Upgrade ke V4.0+ untuk menggunakan optimasi ini.
Contoh:
-- Buat tabel uji.
CREATE TABLE tbl(x int4, y int4);
-- Masukkan data uji.
INSERT INTO tbl VALUES (1,2), (null,200), (1000,null), (10000,20000);
-- Kueri data
SELECT
sum(x + 1),
sum(x + 2),
sum(x - 3),
sum(x - 4)
FROM
tbl;
Rencana kueri menunjukkan x adalah satu-satunya kunci grup.
Untuk menonaktifkan:
-- Nonaktifkan pada tingkat session.
SET hg_experimental_remove_related_group_by_key = off;
-- Nonaktifkan pada tingkat DB.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Mengoptimalkan skema tabel dan indeks
Pilih format penyimpanan
Hologres mendukung penyimpanan row, column, dan hybrid. Pilih berdasarkan workload Anda:
|
Format penyimpanan |
Paling cocok untuk |
Trade-off |
|
Row store |
Kueri titik berdasarkan primary key, UPDATE/DELETE yang sering |
Kinerja pemindaian rentang dan agregasi buruk |
|
Column store |
Analitik, kueri multi-kolom, agregasi |
UPDATE/DELETE dan kueri titik lebih lambat |
|
Hybrid row-columnar store |
Workload campuran |
Overhead penyimpanan lebih tinggi |
Pilih tipe data
-
Gunakan tipe lebih kecil bila memungkinkan (
INTalih-alihBIGINT) -
Tentukan presisi untuk tipe
DECIMAL/NUMERIC. -
Hindari
FLOATatauDOUBLEuntuk kolomGROUP BY. -
Gunakan
TEXTuntuk fleksibilitas. Minimalkan N saat menggunakanVARCHAR(N)atauCHAR(N). -
Gunakan
TIMESTAMPTZdanDATEalih-alihTEXTuntuk tanggal. -
Gunakan tipe data konsisten dalam kondisi join untuk menghindari konversi implisit
Rancang primary key
Primary key menjamin keunikan data. Pilih metode deduplikasi saat mengimpor:
-
ignore: Abaikan data baru.
-
update: Timpa data lama.
Primary key yang tepat meningkatkan rencana eksekusi, terutama untuk kueri GROUP BY.
Dalam mode columnar store, primary key memperlambat penulisan—throughput biasanya 3x lebih tinggi tanpa primary key.
Gunakan tabel partisi
Hologres mendukung partisi tingkat tunggal. Partisi yang tepat mempercepat kueri, tetapi terlalu banyak partisi menghasilkan file kecil dan menurunkan kinerja.
Buat partisi harian untuk data inkremental guna mengisolasi penyimpanan dan akses.
Skenario penerapan:
-
DROP atau TRUNCATE seluruh partisi untuk kinerja lebih baik daripada DELETE dan tidak berdampak pada partisi lain.
-
Isolasi pemindaian hanya ke partisi atau tabel anak tertentu.
-
Gunakan tabel partisi untuk impor real-time periodik. Misalnya, gunakan tanggal sebagai kunci partisi. Contoh pernyataan:
begin;
create table insert_partition(c1 bigint not null, c2 boolean, c3 float not null, c4 text, c5 timestamptz not null) partition by list(c4);
call set_table_property('insert_partition', 'orientation', 'column');
commit;
create table insert_partition_child1 partition of insert_partition for values in('20190707');
create table insert_partition_child2 partition of insert_partition for values in('20190708');
create table insert_partition_child3 partition of insert_partition for values in('20190709');
select * from insert_partition where c4 >= '20190708';
select * from insert_partition_child3;
Pilih indeks yang tepat
Hologres menyediakan beberapa jenis indeks. Definisikan indeks saat membuat tabel:
|
Jenis |
Tujuan |
Contoh kueri |
|
clustering_key |
Kueri rentang dan penyaringan |
|
|
bitmap_columns |
Kueri kesamaan |
|
|
segment_key (juga dikenal sebagai event_time_column) |
Penyaringan berbasis waktu (tingkat file) Penyaringan cepat tingkat file sebelum indeks bitmap atau clustering. Mengikuti prinsip pencocokan prefiks paling kiri (biasanya 1 kolom). Gunakan timestamp non-kosong pertama sebagai segment_key. |
|
Catatan:
-
Clustering key dan segment key mengikuti prinsip pencocokan prefiks paling kiri.
-
Indeks bitmap mendukung kueri AND/OR pada beberapa kolom.
-
Gunakan
segment_keyterlebih dahulu untuk penyaringan berbasis waktu, lalubitmap_columnsuntuk kesamaan atauclustering_keyuntuk kueri rentang.
Contoh:
BEGIN;
CREATE TABLE events (
event_id INT NOT NULL,
user_id INT NOT NULL,
event_time TIMESTAMPTZ NOT NULL,
event_type TEXT
);
CALL set_table_property('events', 'clustering_key', 'event_time');
CALL set_table_property('events', 'segment_key', 'event_time');
CALL set_table_property('events', 'bitmap_columns', 'user_id,event_type');
COMMIT;
bitmap_columns dapat ditambahkan setelah pembuatan tabel. clustering_key dan segment_key harus ditentukan saat pembuatan.
Verifikasi penggunaan indeks dalam kueri dengan menjalankan EXPLAIN:
EXPLAIN SELECT * FROM events WHERE event_time > '2026-01-01';
Nonaktifkan dictionary encoding untuk kolom karakter
Dictionary encoding mempercepat perbandingan string tetapi menambahkan overhead encode/decode. Nonaktifkan untuk kolom di mana biaya perbandingan rendah:
BEGIN;
CREATE TABLE logs (id INT, message TEXT);
CALL set_table_property('logs', 'dictionary_encoding_columns', '');
COMMIT;Mengoptimalkan pernyataan SQL
Hindari SQL eksternal (Postgres) seperti NOT IN
Hologres menggunakan HQE (Hologres Query Engine) untuk kinerja terbaik. Operator yang tidak didukung akan fallback ke PQE (Postgres Query Engine), yang lebih lambat.
Memeriksa fallback ke PQE dalam rencana eksekusi:
EXPLAIN SELECT * FROM orders WHERE id NOT IN (SELECT id FROM cancelled_orders);
Jika Anda melihat External SQL (Postgres), tulis ulang kueri:
|
Tidak didukung HQE |
Tulis ulang menjadi |
Contoh |
Catatan |
|
|
|
|
N/A. |
|
|
|
|
regexp_split_to_table mendukung ekspresi reguler. Mulai Hologres V2.0.4, HQE mendukung |
|
|
|
Tulis ulang sebagai:
|
Beberapa versi V0.10 dan sebelumnya tidak mendukung substring. Mulai V1.3, HQE mendukung input non-regex untuk substring. |
|
|
|
Tulis ulang sebagai:
|
|
|
|
Hapus |
Tulis ulang sebagai:
|
N/A. |
|
|
|
Tulis ulang sebagai:
|
Didukung oleh HQE mulai Hologres V2.0. |
|
|
|
Tulis ulang sebagai:
|
Didukung oleh HQE mulai Hologres V2.0. |
Hindari kueri LIKE fuzzy
Hindari pencarian fuzzy seperti operasi LIKE karena tidak menggunakan indeks.
Mengoptimalkan kueri ORDER BY LIMIT
Sejak V1.3, Hologres mendukung Merge Sort untuk kueri ORDER BY ... LIMIT, sehingga menghilangkan operasi sort berlebihan.
Mengoptimalkan kueri GROUP BY
Tetapkan kolom GROUP BY sebagai distribution key untuk mengurangi redistribusi data.
-- Jika data didistribusikan berdasarkan nilai pada kolom a, redistribusi data saat runtime berkurang, dan kemampuan komputasi paralel shard dimanfaatkan sepenuhnya.
select a, count(1) from t1 group by a;
Sejak V4.0, Hologres secara otomatis menulis ulang kolom GROUP BY terkait untuk mengurangi penggabungan (kedalaman pencarian maks: 5 lapis). Klausa seperti GROUP BY COL_A, ((COL_A + 1)), ((COL_A + 2)) ditulis ulang menjadi GROUP BY COL_A. Contoh:
CREATE TABLE tbl (
a int,
b int,
c int
);
-- Kueri
SELECT
a,
a + 1 as a1,
a + 2 as a2,
sum(b)
FROM tbl
GROUP BY
a,
a1,
a2;
Rencana eksekusi mengonfirmasi penulisan ulang—klausa GROUP BY hanya berisi kolom a.
QUERY PLAN
Gather (cost=0.00..5.00 rows=1 width=20)
-> Project (cost=0.00..5.00 rows=1 width=20)
-> HashAggregate (cost=0.00..5.00 rows=1 width=12)
Group Key: a
-> Redistribution (cost=0.00..5.00 rows=1 width=8)
Hash Key: a
-> Local Gather (cost=0.00..5.00 rows=1 width=8)
-> Seq Scan on tbl (cost=0.00..5.00 rows=1 width=8)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0
Untuk menonaktifkan:
-- Nonaktifkan fitur ini pada tingkat session.
SET hg_experimental_remove_related_group_by_key = off;
-- Nonaktifkan fitur ini pada tingkat database.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Aktifkan penggunaan kembali CTE
Saat CTE dirujuk beberapa kali, aktifkan reuse CTE untuk menghindari komputasi ulang (V1.3+):
SET optimizer_cte_inlining=off;
-
Reuse CTE secara default dinonaktifkan. Aktifkan secara manual melalui GUC.
-
Reuse CTE bergantung pada Spill pada tahap Shuffle. Volume data besar dapat memengaruhi kinerja akibat laju konsumsi yang berbeda-beda.
Mengoptimalkan analisis Top-N
-
Dalam skenario OLAP, mengambil N record teratas dalam suatu grup merupakan kebutuhan umum. Misalnya, kueri SQL berikut mengambil dua record teratas dari tabel
tdalam setiap partisib, diurutkan berdasarkana:CREATE TABLE t ( a int, b int ); INSERT INTO t VALUES (2, 1), (3, 1), (4, 1), (5, 2), (6, 2); SELECT * FROM ( SELECT a, b, row_number() OVER (PARTITION BY b ORDER BY a) AS rn FROM t) t1 WHERE rn <= 2;Hasil eksekusi adalah sebagai berikut:
a b rn 5 2 1 6 2 2 2 1 1 3 1 2 -
Mulai Hologres V4.1, operator
Partition Sortmendorong klausaLIMITke dalamPartition, sehingga menyaring data lebih awal selama pengurutan. Ini mengurangi memori untuk fungsi jendela sepertirow_numberdanrankdalam skenario Top-N, sehingga menurunkan risiko OOM. Diaktifkan secara default. Untuk menonaktifkan:-- Nonaktifkan fitur ini pada tingkat session. SET hg_experimental_enable_hash_partitioned_sort_v2 = off; -- Nonaktifkan fitur ini pada tingkat database. ALTER DATABASE <database_name> SET hg_experimental_enable_hash_partitioned_sort_v2 = off;
Menangani data skew
Distribusi data yang tidak merata memperlambat kueri. Periksa jumlah baris per shard untuk mendeteksi skew:
-- hg_shard_id adalah kolom tersembunyi bawaan di setiap tabel yang menggambarkan shard tempat baris data terkait berada.
SELECT hg_shard_id, count(1) FROM t1 GROUP BY hg_shard_id;
Jika beberapa shard memiliki jumlah baris jauh lebih banyak daripada yang lain:
-
Ubah
distribution_keymenjadi kolom dengan distribusi data yang merata.PentingMengubah distribution key memerlukan pembuatan ulang tabel dan pengimporan ulang data.
-
Jika data memang skew secara inheren, optimalkan dari perspektif bisnis
Nonaktifkan caching hasil untuk pengujian
Hologres secara default menyimpan cache hasil kueri. Nonaktifkan caching saat melakukan benchmark kinerja:
set hg_experimental_enable_result_cache = off;