Hologres mendukung tiga format penyimpanan tabel: berorientasi baris, berorientasi kolom, dan hibrida. Setiap format dioptimalkan untuk skenario kueri yang berbeda. Pilih format penyimpanan yang sesuai dengan kasus penggunaan Anda untuk meningkatkan pemrosesan data dan performa kueri secara signifikan sekaligus mengurangi konsumsi penyimpanan.
Sintaksis Pengaturan Format Penyimpanan
Hologres mendukung tiga format penyimpanan: berorientasi baris, berorientasi kolom, dan hibrida. Tentukan format penyimpanan tabel dengan mengatur properti orientation saat membuat tabel, sebagai berikut:
-- Didukung mulai V2.1
CREATE TABLE <table_name> (...) WITH (orientation = '[column | row | row,column]');
-- Didukung oleh semua versi
BEGIN;
CREATE TABLE <table_name> (...);
CALL set_table_property('<table_name>', 'orientation', '[column | row | row,column]');
COMMIT;table_name: Nama tabel.
orientation: Menentukan apakah mode penyimpanan tabel database di Hologres berorientasi kolom atau berorientasi baris. Hologres mendukung mode hibrida mulai dari V1.1.
Secara default, tabel yang dibuat berorientasi kolom (penyimpanan kolom). Secara eksplisit tentukan penyimpanan berorientasi baris atau hibrida saat membuat tabel. Untuk mengubah format penyimpanan tabel, Anda harus membuat ulang tabel tersebut karena konversi langsung tidak didukung.
Rekomendasi Penggunaan
Tabel berikut memberikan rekomendasi untuk memilih format penyimpanan tabel.
Format Penyimpanan | Skenario | Batas Kolom | Penggunaan |
Berorientasi Kolom | Cocok untuk skenario OLAP yang melibatkan kueri kompleks, join data, pemindaian, penyaringan, dan analisis statistik. | Disarankan memiliki tidak lebih dari 300 kolom. | Penyimpanan berorientasi kolom membuat beberapa indeks secara default, termasuk indeks bitmap untuk tipe string. Indeks ini secara signifikan mempercepat operasi penyaringan dan statistik kueri. |
Berorientasi Baris | Cocok untuk kueri titik berdasarkan kunci primer, seperti pada pernyataan kueri berikut. | Disarankan memiliki tidak lebih dari 3000 kolom. | Penyimpanan berorientasi baris hanya membuat indeks untuk kunci primer secara default, sehingga hanya mendukung pencarian cepat pada kolom kunci primer. Hal ini membatasi penerapannya pada skenario tertentu. |
Koeksistensi Baris dan Kolom | Mendukung semua skenario berorientasi baris dan berorientasi kolom, termasuk kueri titik non-kunci primer. | Disarankan memiliki tidak lebih dari 300 kolom. | Penyimpanan hibrida berlaku untuk rentang skenario yang lebih luas tetapi menimbulkan overhead penyimpanan yang lebih tinggi serta biaya sinkronisasi data internal. |
Prinsip Teknis
Berorientasi Kolom
Pada tabel berorientasi kolom, data disimpan per kolom. Penyimpanan berorientasi kolom menggunakan format ORC secara default. Data dikodekan menggunakan berbagai algoritma pengkodean (seperti RLE dan dictionary encoding), lalu dikompresi lebih lanjut dengan algoritma kompresi utama (seperti Snappy, Zlib, Zstd, dan Lz4). Pendekatan ini, dikombinasikan dengan mekanisme seperti indeks bitmap dan materialisasi terlambat, meningkatkan efisiensi penyimpanan maupun performa kueri.
Sistem menyimpan file indeks kunci primer untuk setiap tabel di lapisan penyimpanan dasar. Untuk informasi selengkapnya, lihat Primary Key. Jika tabel berorientasi kolom memiliki kunci primer (PK) yang dikonfigurasi, sistem secara otomatis menghasilkan Row Identifier (RID) untuk menemukan seluruh baris data dengan cepat. Selain itu, jika indeks yang sesuai—seperti Distribution Key atau Clustering Key—didefinisikan pada kolom yang dikueri, sistem dapat menggunakannya untuk menemukan shard dan file tempat data berada, sehingga meningkatkan performa kueri. Akibatnya, tabel berorientasi kolom cocok untuk berbagai skenario dan biasanya digunakan untuk kueri OLAP. Contoh berikut mengilustrasikan konsep ini.
Sintaksis pembuatan tabel yang didukung mulai V2.1:
CREATE TABLE public.tbl_col ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT NOT NULL, in_time TIMESTAMPTZ NOT NULL, PRIMARY KEY (id) ) WITH ( orientation = 'column', clustering_key = 'class', bitmap_columns = 'name', event_time_column = 'in_time' ); SELECT * FROM public.tbl_col WHERE id ='3333'; SELECT id, class,name FROM public.tbl_col WHERE id < '3333' ORDER BY id;Sintaksis pembuatan tabel yang didukung oleh semua versi:
BEGIN; CREATE TABLE public.tbl_col ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT NOT NULL, in_time TIMESTAMPTZ NOT NULL, PRIMARY KEY (id) ); CALL set_table_property('public.tbl_col', 'orientation', 'column'); CALL set_table_property('public.tbl_col', 'clustering_key', 'class'); CALL set_table_property('public.tbl_col', 'bitmap_columns', 'name'); CALL set_table_property('public.tbl_col', 'event_time_column', 'in_time'); COMMIT; SELECT * FROM public.tbl_col WHERE id ='3333'; SELECT id, class,name FROM public.tbl_col WHERE id < '3333' ORDER BY id;
Diagramnya sebagai berikut.
Berorientasi Baris
Pada tabel berorientasi baris, data disimpan per baris. Penyimpanan berorientasi baris menggunakan format SST secara default. Data disimpan dalam blok terkompresi yang diurutkan berdasarkan kunci. Indeks seperti Block Index dan Bloom Filter, bersama dengan mekanisme kompaksi latar belakang, mengorganisasi file untuk mengoptimalkan efisiensi kueri titik.
(Direkomendasikan) Atur Primary Key
Sistem menyimpan file indeks kunci primer untuk setiap tabel di lapisan penyimpanan dasar. Untuk informasi selengkapnya, lihat Primary Key. Saat tabel berorientasi baris memiliki kunci primer (PK), sistem secara otomatis menghasilkan row identifier (RID) untuk menemukan seluruh baris data. Sistem juga menetapkan PK sebagai Distribution Key sekaligus Clustering Key, sehingga memungkinkan penentuan lokasi shard dan file yang berisi data secara cepat. Untuk kueri berdasarkan kunci primer, sistem hanya memindai satu indeks kunci primer untuk mengambil semua kolom dari seluruh baris secara cepat, sehingga meningkatkan efisiensi kueri. Berikut adalah contoh SQL-nya.
Sintaksis pembuatan tabel yang didukung mulai V2.1:
CREATE TABLE public.tbl_row ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT, PRIMARY KEY (id) ) WITH ( orientation = 'row', clustering_key = 'id', distribution_key = 'id' ); -- Contoh kueri titik berbasis PK SELECT * FROM public.tbl_row WHERE id ='1111'; -- Kueri beberapa kunci SELECT * FROM public.tbl_row WHERE id IN ('1111','2222','3333');Sintaksis pembuatan tabel yang didukung oleh semua versi:
BEGIN; CREATE TABLE public.tbl_row ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT , PRIMARY KEY (id) ); CALL set_table_property('public.tbl_row', 'orientation', 'row'); CALL set_table_property('public.tbl_row', 'clustering_key', 'id'); CALL set_table_property('public.tbl_row', 'distribution_key', 'id'); COMMIT; -- Contoh kueri titik berbasis PK SELECT * FROM public.tbl_row WHERE id ='1111'; -- Kueri beberapa kunci SELECT * FROM public.tbl_row WHERE id IN ('1111','2222','3333');
Diagramnya sebagai berikut.

(Tidak Direkomendasikan) Pengaturan PK dan Clustering Key yang tidak konsisten
Jika Anda membuat tabel berorientasi baris dan menetapkan bidang yang berbeda untuk PK dan Clustering Key, sistem terlebih dahulu menemukan Clustering Key dan RID berdasarkan PK selama kueri. Kemudian sistem menggunakan Clustering Key dan RID tersebut untuk mengambil data baris lengkap. Hal ini memerlukan dua kali pemindaian dan mengakibatkan penurunan performa. Contoh SQL-nya sebagai berikut.
Sintaksis pembuatan tabel yang didukung mulai V2.1, mengatur tabel berorientasi baris dengan PK dan Clustering Key yang tidak konsisten:
CREATE TABLE public.tbl_row ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT, PRIMARY KEY (id) ) WITH ( orientation = 'row', clustering_key = 'name', distribution_key = 'id' );Sintaksis pembuatan tabel yang didukung oleh semua versi, mengatur tabel berorientasi baris dengan PK dan Clustering Key yang tidak konsisten:
BEGIN; CREATE TABLE public.tbl_row ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT , PRIMARY KEY (id) ); CALL set_table_property('public.tbl_row', 'orientation', 'row'); CALL set_table_property('public.tbl_row', 'clustering_key', 'name'); CALL set_table_property('public.tbl_row', 'distribution_key', 'id'); COMMIT;
Diagramnya sebagai berikut.

Ringkasnya: Tabel berorientasi baris sangat cocok untuk skenario kueri titik berbasis kunci primer, memungkinkan kueri titik QPS tinggi. Saat membuat tabel, cukup definisikan PK saja. Sistem secara otomatis mengonfigurasi PK sebagai Distribution Key sekaligus Clustering Key untuk mengoptimalkan performa kueri. Hindari menetapkan bidang yang berbeda untuk PK dan Clustering Key karena akan menurunkan performa.
Hibrida
Dalam aplikasi nyata, sebuah tabel mungkin digunakan baik untuk kueri titik berbasis kunci primer maupun kueri OLAP. Oleh karena itu, Hologres V1.1 memperkenalkan penyimpanan hibrida. Penyimpanan hibrida menggabungkan kemampuan penyimpanan berorientasi baris dan berorientasi kolom, mendukung kueri titik berbasis kunci primer berkinerja tinggi serta analisis OLAP. Di lapisan dasar, data disimpan dua kali—sekali dalam format berorientasi baris dan sekali dalam format berorientasi kolom—sehingga menghasilkan overhead penyimpanan yang lebih tinggi.
Selama penulisan data, sistem secara bersamaan menulis salinan berorientasi baris dan berorientasi kolom. Operasi hanya mengembalikan status sukses setelah kedua salinan berhasil ditulis, sehingga menjamin atomisitas data.
Selama kueri, pengoptimal mengurai pernyataan SQL untuk menghasilkan rencana eksekusi. Mesin eksekusi kemudian memilih format penyimpanan—berorientasi baris atau berorientasi kolom—yang memberikan efisiensi kueri lebih tinggi berdasarkan rencana tersebut. Tabel hibrida harus memiliki kunci primer yang didefinisikan:
Untuk skenario kueri titik berbasis kunci primer (seperti pernyataan
select * from tbl where pk=xxx) dan skenario yang menggunakan Fixed Plan untuk mempercepat eksekusi SQL, pengoptimal secara default memilih jalur kueri titik berorientasi baris berbasis kunci primer.Untuk skenario kueri titik non-kunci primer (seperti pernyataan
select * from tbl where col1=xx and col2=yyy), terutama ketika tabel memiliki banyak kolom dan hasil kueri mencakup banyak kolom, penyimpanan hibrida memberikan optimasi signifikan. Selama pembuatan rencana eksekusi, pengoptimal pertama-tama membaca data dari tabel berorientasi kolom. Kemudian menggunakan nilai kunci yang diambil untuk mengambil baris yang sesuai dari tabel berorientasi baris. Hal ini menghindari pemindaian tabel penuh dan meningkatkan performa untuk kueri non-kunci primer. Skenario ini sepenuhnya memanfaatkan keunggulan penyimpanan hibrida untuk meningkatkan kecepatan pengambilan data.Untuk kueri umum lainnya, sistem secara default menggunakan penyimpanan berorientasi kolom.
Oleh karena itu, tabel hibrida memberikan efisiensi kueri yang unggul dalam skenario umum, terutama untuk kueri titik non-kunci primer. Contohnya sebagai berikut.
Sintaksis pembuatan tabel yang didukung mulai V2.1:
CREATE TABLE public.tbl_row_col ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT NOT NULL, PRIMARY KEY (id) ) WITH ( orientation = 'row,column', distribution_key = 'id', clustering_key = 'class', bitmap_columns = 'name' ); SELECT * FROM public.tbl_row_col WHERE id ='2222'; -- Kueri titik berbasis PK SELECT * FROM public.tbl_row_col WHERE class='Class Two';-- Kueri titik non-PK SELECT * FROM public.tbl_row_col WHERE id ='2222' AND class='Class Two'; -- Kueri OLAP umumSintaksis pembuatan tabel yang didukung oleh semua versi:
BEGIN; CREATE TABLE public.tbl_row_col ( id TEXT NOT NULL, name TEXT NOT NULL, class TEXT , PRIMARY KEY (id) ); CALL set_table_property('public.tbl_row_col', 'orientation','row,column'); CALL set_table_property('public.tbl_row_col', 'distribution_key','id'); CALL set_table_property('public.tbl_row_col', 'clustering_key','class'); CALL set_table_property('public.tbl_row_col', 'bitmap_columns','name'); COMMIT; SELECT * FROM public.tbl_row_col WHERE id ='2222'; -- Kueri titik berbasis PK SELECT * FROM public.tbl_row_col WHERE class='Class Two';-- Kueri titik non-PK SELECT * FROM public.tbl_row_col WHERE id ='2222' AND class='Class Two'; -- Kueri OLAP umum
Diagramnya sebagai berikut.
Contoh Penggunaan
Contoh berikut menunjukkan cara membuat tabel dengan format penyimpanan yang berbeda.
Sintaksis pembuatan tabel yang didukung mulai versi V2.1:
-- Buat tabel berorientasi baris CREATE TABLE public.tbl_row ( a INTEGER NOT NULL, b TEXT NOT NULL, PRIMARY KEY (a) ) WITH ( orientation = 'row' ); -- Buat tabel berorientasi kolom CREATE TABLE tbl_col ( a INT NOT NULL, b TEXT NOT NULL ) WITH ( orientation = 'column' ); -- Buat tabel dengan penyimpanan baris dan kolom CREATE TABLE tbl_col_row ( pk TEXT NOT NULL, col1 TEXT, col2 TEXT, col3 TEXT, PRIMARY KEY (pk) ) WITH ( orientation = 'row,column' );Sintaksis pembuatan tabel yang didukung di semua versi:
-- Buat tabel berorientasi baris BEGIN; CREATE TABLE public.tbl_row ( a INTEGER NOT NULL, b TEXT NOT NULL, PRIMARY KEY (a) ); CALL set_table_property('public.tbl_row', 'orientation', 'row'); COMMIT; -- Buat tabel berorientasi kolom BEGIN; CREATE TABLE tbl_col ( a INT NOT NULL, b TEXT NOT NULL); CALL set_table_property('tbl_col', 'orientation', 'column'); COMMIT; -- Buat tabel dengan penyimpanan baris dan kolom BEGIN; CREATE TABLE tbl_col_row ( pk TEXT NOT NULL, col1 TEXT, col2 TEXT, col3 TEXT, PRIMARY KEY (pk)); CALL set_table_property('tbl_col_row', 'orientation', 'row,column'); COMMIT;
Referensi
Untuk informasi selengkapnya tentang pengaturan properti tabel yang sesuai berdasarkan skenario kueri bisnis, lihat Panduan Optimasi Pembuatan Tabel Berbasis Skenario.