All Products
Search
Document Center

Lindorm:Mengakses data berorientasi kolom

Last Updated:Mar 29, 2026

Lindorm column-oriented storage adalah layanan penyimpanan terdistribusi berbasis kolom yang menyimpan dan memproses data berdasarkan kolom. Dibandingkan dengan penyimpanan berorientasi baris, layanan ini mengurangi waktu respons kueri dan menghemat sumber daya I/O. Gunakan mesin komputasi Lindorm untuk membuat namespace dan tabel, membaca serta menulis data, melakukan compact file, dan mengonfigurasi penyimpanan bertingkat.

Ikhtisar

Penyimpanan berorientasi kolom cocok untuk volume besar data semi-terstruktur dan terstruktur dalam skenario seperti Internet of Vehicles (IoV), Internet of Things (IoT), pesanan, dan log. Kemampuan utamanya meliputi:

  • Komputasi dan analitik: Lakukan analitik interaktif dan komputasi online pada data berorientasi kolom. Kemampuan pengindeksan yang lengkap mempercepat penentuan posisi data. Tambahkan, hapus, ubah, dan kueri volume besar data kunci primer menggunakan pernyataan SQL.

  • Throughput tinggi: Mendukung skalabilitas horizontal dengan kemampuan membaca dan menulis data hingga terabyte per menit—cocok untuk impor data IoV cepat, akses set data pelatihan model, dan analisis laporan berskala besar.

  • Hemat biaya: Menggunakan algoritma rasio kompresi tinggi berbasis kolom, media berkepadatan tinggi berbiaya rendah, pemisahan data panas dan dingin, encoding kompresi, serta penyimpanan arsip data dingin untuk mengurangi biaya penyimpanan.

  • Ketersediaan tinggi: Menggunakan erasure coding untuk memastikan ketersediaan tinggi dataset terdistribusi dan menghilangkan risiko single point of failure (SPOF).

  • Kompatibilitas open source: Kompatibel dengan API Iceberg dan terhubung ke mesin komputasi seperti Spark dan Flink untuk integrasi tanpa hambatan ke dalam ekosistem data utama.

  • Pemisahan data panas dan dingin: Simpan data panas dan dingin pada media penyimpanan berbeda sesuai kebutuhan bisnis Anda guna mengurangi beban kinerja dan menekan biaya penyimpanan.

Prasyarat

Sebelum memulai, pastikan Anda telah:

DDL

Namespace

Buat namespace (database).

USE lindorm_columnar;
CREATE NAMESPACE mydb;

Hapus namespace (database).

USE lindorm_columnar;
DROP NAMESPACE mydb;

Table

Buat tabel.

Buat tabel

Contoh berikut membuat tabel kunci primer dengan partisi reguler dan partisi bucket:

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id   INT    NOT NULL,
  city STRING NOT NULL,
  name STRING,
  score INT)
PARTITIONED BY (city, bucket(128, id))
TBLPROPERTIES (
  'primary-key' = 'id,city');

Tabel kunci primer vs. tabel non-kunci primer

Tabel kunci primerTabel non-kunci primer
Cara membuatTentukan 'primary-key' di dalam TBLPROPERTIESAbaikan 'primary-key' dari TBLPROPERTIES
Keunikan dataKunci primer unik; tulisan duplikat akan menimpa data yang adaTidak ada jaminan keunikan; baris duplikat mungkin ada
PartisiWajib; bidang ekspresi partisi harus merupakan bidang kunci primer; partisi tingkat terakhir harus berupa partisi bucketTidak wajib
Jenis kunci primer yang didukungBOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, STRING, BINARYN/A

Ekspresi partisi

Gunakan PARTITIONED BY untuk menentukan cara data didistribusikan ke dalam partisi. Sintaksnya adalah:

PARTITIONED BY ([regular partition expression, ...] {bucket(bucketNum, bucketCol)})

Tabel berikut menjelaskan fungsi transformasi partisi yang tersedia:

FungsiDeskripsiJenis yang didukungCatatan penggunaan
bucket(N, col)Mendistribusikan data ke dalam N shard dengan melakukan penghashan nilai kolomBOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, STRING, BINARYbucketNum secara langsung memengaruhi konkurensi tulis dan pemindaian; partisi tingkat terakhir harus berupa partisi bucket untuk tabel kunci primer
col_name (identity)Membuat satu partisi fisik untuk setiap nilai unikSemua jenisGunakan nilai terkonsentrasi seperti tanggal, kota, atau jenis kelamin; hindari nilai diskret seperti timestamp yang menghasilkan metadata berlebihan

Menentukan ukuran `bucketNum`: Evaluasi total volume data sebelum membuat tabel dan pilih bucketNum sehingga setiap partisi bucket menyimpan data sebesar 50–512 MB. Indeks bucket dihitung sebagai bucket_index = hash(bucketCol) % bucketNum.

Menghindari kesenjangan data: Pastikan nilai bucketCol bersifat diskret.

Contoh partisi hanya bucket

Contoh 1: Kunci primer satu kolom, hanya partisi bucket:

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id    INT    NOT NULL,
  city  STRING,
  name  STRING,
  score DOUBLE)
PARTITIONED BY (bucket(1024, id))
TBLPROPERTIES (
  'primary-key' = 'id');

Contoh 2: Kunci primer komposit, hanya partisi bucket:

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id        INT  NOT NULL,
  timestamp LONG NOT NULL,
  city      STRING,
  name      STRING,
  score     DOUBLE)
PARTITIONED BY (bucket(512, timestamp))
TBLPROPERTIES (
  'primary-key' = 'id,timestamp');

Contoh partisi reguler + partisi bucket

Contoh 1: Partisi reguler berbasis tanggal dengan bucket:

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id    INT    NOT NULL,
  year  STRING NOT NULL,
  month STRING NOT NULL,
  day   STRING NOT NULL,
  city  STRING,
  name  STRING,
  score DOUBLE)
PARTITIONED BY (year, month, day, bucket(1024, id))
TBLPROPERTIES (
  'primary-key' = 'id,year,month,day');

Contoh 2: Partisi reguler multi-kolom dengan bucket:

USE lindorm_columnar;
CREATE TABLE mydb.mytable (
  id    INT    NOT NULL,
  date  STRING NOT NULL,
  city  STRING NOT NULL,
  name  STRING,
  score DOUBLE)
PARTITIONED BY (date, city, bucket(1024, id))
TBLPROPERTIES (
  'primary-key' = 'id,date,city');

Lihat tabel dalam namespace saat ini.

USE lindorm_columnar;
USE mydb;
SHOW TABLES;

Lihat tabel yang ada.

Anda dapat menjalankan pernyataan SQL berikut untuk melihat skema tabel.

USE lindorm_columnar;
SHOW CREATE TABLE mydb.mytable;
DESC mydb.mytable;

Hapus tabel tertentu.

USE lindorm_columnar;
-- Hapus tabel tetapi simpan file datanya.
DROP TABLE mydb.mytable;
-- Hapus tabel dan semua file datanya.
DROP TABLE mydb.mytable PURGE;

Bersihkan data dalam tabel.

USE lindorm_columnar;
TRUNCATE TABLE mydb.mytable;

Partition

Hapus partisi.

Gunakan DELETE FROM dengan klausa WHERE untuk menghapus partisi:

USE lindorm_columnar;
DELETE FROM mydb.mytable WHERE city = 'beijing';

DML

Table

Masukkan data ke dalam tabel.

  • Contoh 1:

    USE lindorm_columnar;
    INSERT INTO mydb.mytable VALUES (0, 'beijing', 'zhang3', 99);
  • Contoh 2:

    USE lindorm_columnar;
    INSERT INTO mydb.mytable SELECT id, city, name, score FROM another_table;

Kueri data dalam tabel.

  • Contoh 1:

    USE lindorm_columnar;
    SELECT * FROM mydb.mytable WHERE id = 0;
  • Contoh 2:

    USE lindorm_columnar;
    SELECT count(1), sum(score) FROM mydb.mytable WHERE city = 'beijing';

Manajemen Partisi

Seiring waktu, penulisan inkremental menghasilkan banyak file kecil. Melakukan compact file-file tersebut menjadi file yang lebih besar mengurangi redundansi data dan metadata serta meningkatkan kinerja kueri. Gunakan rewrite_data_files atau rewrite_manifest untuk memicu proses compact.

Penting

Kedua perintah ini mengonsumsi sumber daya database. Jalankan selama jam sepi.

Compact semua file dalam tabel:

USE lindorm_columnar;
CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');

Compact file dalam partisi tertentu:

USE lindorm_columnar;
CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');

Tulis ulang manifes tabel:

USE lindorm_columnar;
CALL lindorm_columnar.system.rewrite_manifest('mydb.mytable');

Untuk referensi perintah lengkap, lihat rewrite_data_files dan rewrite_manifest.

Penyimpanan data panas dan dingin

Lindorm mendukung pemisahan data panas dan dingin tiga tingkat (L1, L2, L3). Data yang sering diakses tetap berada di penyimpanan berkinerja tinggi; data lama secara otomatis dipindahkan ke penyimpanan berbiaya lebih rendah. Layanan data lake menangani proses dumping secara asinkron—kueri tetap tersedia selama proses berlangsung, meskipun kinerja akses bervariasi di antara tingkat penyimpanan.

Penting

Untuk mengaktifkan konversi otomatis data panas-dingin untuk data berorientasi kolom, hubungi dukungan teknis Lindorm (DingTalk ID: s0s3eg3).

Kebijakan pemisahan panas-dingin hanya berlaku berdasarkan partisi waktu.

Parameter CHS

Konfigurasikan atribut cold/hot storage (CHS) di dalam TBLPROPERTIES saat membuat atau mengubah tabel.

ParameterDeskripsiFormatDefault
CHSAmbang batas waktu (dalam detik) yang menentukan kapan data berpindah antar tingkat penyimpanan. Satu nilai = pemisahan L1/L2. Dua nilai (num0, num1 dengan num0 < num1) = pemisahan L1/L2/L3.Bilangan bulat panjang, satuan: detik
CHS_L1Jenis penyimpanan untuk tingkat L1 (panas)'CHS_L1'='storagetype=<storage type>'CAPACITY_CLOUD_STORAGE
CHS_L2Jenis penyimpanan untuk tingkat L2. Wajib ditentukan jika CHS diatur.Format sama seperti CHS_L1
CHS_L3Jenis penyimpanan untuk tingkat L3 (paling dingin). Wajib ditentukan jika CHS memiliki dua nilai.Format sama seperti CHS_L1
CHS_EXPEkspresi yang mengekstraksi waktu data dari bidang partisi waktu, digunakan untuk dibandingkan dengan ambang batas CHS.toSec(col0, pattern0, col1, pattern1, ...)

Jenis penyimpanan yang didukung

Untuk penyimpanan cloud: CAPACITY_CLOUD_STORAGE (default), STANDARD_CLOUD_STORAGE, PERFORMANCE_CLOUD_STORAGE, CLOUD_ARCHIVE_STORAGE

Penyimpanan arsip (CLOUD_ARCHIVE_STORAGE) sedang dalam pratinjau internal. Hubungi dukungan teknis Lindorm (DingTalk ID: s0s3eg3) untuk mengaktifkannya.

Untuk disk lokal: CAPACITY_CLOUD_STORAGE (default), LOCAL_SSD_STORAGE, LOCAL_HDD_STORAGE, LOCAL_EBS_STORAGE

Token pola `CHS_EXP`

Pola tokenMakna
yyyyTahun
MMBulan
ddHari
HHJam
mmMenit

Fungsi toSec() menghitung waktu data maksimum untuk partisi yang cocok. Misalnya, untuk partisi year=2023, month=10, day=2:

  • toSec(year, yyyy) mengembalikan 2023-12-31 23:59:59

  • toSec(year, yyyy, month, MM) mengembalikan 2023-10-31 23:59:59

  • toSec(year, yyyy, month, MM, day, dd) mengembalikan 2023-10-02 23:59:59

Untuk satu bidang tanggal gabungan, misalnya date=2023-10-02:

  • toSec(date, yyyy-MM-dd) mengembalikan 2023-10-02 23:59:59

Contoh

Contoh 1: Pindahkan data yang lebih tua dari satu bulan (2.592.000 detik) ke Capacity storage (L2):

CREATE TABLE table0 (col0 INT, year STRING, month STRING, day STRING)
PARTITIONED BY (year, month)
TBLPROPERTIES (
  'CHS'    = '2592000',
  'CHS_L2' = 'storagetype=CAPACITY_CLOUD_STORAGE',
  'CHS_EXP'= 'toSec(year,yyyy,month,MM,day,dd)'
);

Contoh 2: Perbarui kebijakan pada table0—pindahkan data yang lebih tua dari satu bulan ke Capacity storage, dan data yang lebih tua dari tiga bulan (5.184.000 detik) ke penyimpanan arsip:

ALTER TABLE table0
SET TBLPROPERTIES (
  'CHS'    = '2592000,5184000',
  'CHS_L2' = 'storagetype=CAPACITY_CLOUD_STORAGE',
  'CHS_L3' = 'storagetype=CLOUD_ARCHIVE_STORAGE',
  'CHS_EXP'= 'toSec(year,yyyy,month,MM,day,dd)'
);

Contoh 3: Buat tabel dengan satu bidang partisi dt (format: yyyy/MM/dd, misalnya 2020/12/1). Pindahkan data yang lebih tua dari satu bulan ke Capacity storage dan data yang lebih tua dari tiga bulan ke penyimpanan arsip:

CREATE TABLE table1 (col0 INT, dt STRING)
PARTITIONED BY (dt)
TBLPROPERTIES (
  'CHS'    = '2592000,5184000',
  'CHS_L2' = 'storagetype=CAPACITY_CLOUD_STORAGE',
  'CHS_L3' = 'storagetype=CLOUD_ARCHIVE_STORAGE',
  'CHS_EXP'= 'toSec(dt,yyyy/MM/dd)'
);

Catatan penggunaan

  • Tetapkan CHS saat membuat tabel, atau perbarui nanti dengan ALTER TABLE ... SET TBLPROPERTIES.

  • Jika CHS dikonfigurasi salah, tabel berhasil dibuat atau diperbarui, tetapi data tidak secara otomatis dipindahkan antar tingkat penyimpanan.

  • Dumping berjalan secara asinkron. Data tetap dapat diakses selama proses berlangsung, tetapi kinerja akses mungkin bervariasi tergantung pada tingkat penyimpanan.

  • Pemisahan panas-dingin hanya didukung untuk partisi berbasis waktu.

Praktik terbaik

Tentukan kunci primer untuk kueri titik

Pencarian berdasarkan kunci primer merupakan jalur kueri tercepat. Untuk tabel besar, tentukan kunci primer dan lakukan kueri dalam rentang kunci sempit untuk kinerja terbaik.

Tabel contoh:

USE lindorm_columnar;
CREATE TABLE orders (
  o_orderkey      INT    NOT NULL,
  o_custkey       INT,
  o_orderstatus   STRING,
  o_totalprice    DOUBLE,
  o_orderdate     STRING,
  o_orderpriority STRING,
  o_clerk         STRING,
  o_shippriority  INT,
  o_comment       STRING)
PARTITIONED BY (bucket(1024, o_orderkey))
TBLPROPERTIES (
  'primary-key' = 'o_orderkey');

Pencarian titik:

USE lindorm_columnar;
SELECT * FROM orders WHERE o_orderkey = 18394;

Pemindaian rentang (rentang sempit memberikan kinerja lebih baik):

USE lindorm_columnar;
SELECT count(*) FROM orders WHERE o_orderkey > 100000 AND o_orderkey < 200000;

Tambahkan partisi untuk mengisolasi data

Partisi dalam mesin penyimpanan berorientasi kolom secara fisik terisolasi. Kueri yang difilter berdasarkan kunci partisi akan melewati partisi yang tidak relevan sepenuhnya.

Tabel contoh dengan partisi tanggal:

USE lindorm_columnar;
CREATE TABLE orders (
  o_orderkey      INT    NOT NULL,
  o_custkey       INT,
  o_orderstatus   STRING,
  o_totalprice    DOUBLE,
  o_orderdate     STRING  NOT NULL,
  o_orderpriority STRING,
  o_clerk         STRING,
  o_shippriority  INT,
  o_comment       STRING)
PARTITIONED BY (o_orderdate, bucket(1024, o_orderkey))
TBLPROPERTIES (
  'primary-key' = 'o_orderdate,o_orderkey');

Kueri data satu hari:

USE lindorm_columnar;
SELECT o_orderdate, count(*) FROM orders WHERE o_orderdate = '2022-01-01' GROUP BY o_orderdate;

Kueri rentang tanggal:

USE lindorm_columnar;
SELECT o_orderdate, count(*)
FROM orders
WHERE o_orderdate >= '2022-01-01' AND o_orderdate <= '2022-01-07'
GROUP BY o_orderdate;

Tingkatkan kinerja pemindaian dengan compact data

Setelah compact menggunakan rewrite_data_files, data diurutkan berdasarkan kunci primer dalam setiap partisi, yang secara signifikan meningkatkan kinerja pemindaian. Untuk hanya mengkueri data yang telah dicompact dan melewati data inkremental, atur read.scan-major-rewritten-files-only ke true.

Tabel contoh:

CREATE TABLE mydb.mytable (
  id    INT    NOT NULL,
  city  STRING NOT NULL,
  name  STRING,
  score INT)
PARTITIONED BY (city, bucket(4, id))
TBLPROPERTIES (
  'primary-key' = 'id,city');

Memadatkan seluruh tabel:

CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');

Compact partisi tertentu:

CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');

Batasi kueri hanya pada data yang telah dicompact:

ALTER TABLE mydb.mytable SET TBLPROPERTIES ('read.scan-major-rewritten-files-only' = true);
NilaiPerilaku
trueHanya mengkueri data yang telah dicompact; data inkremental dikecualikan
false (default)Mengkueri semua data, termasuk data inkremental

Akselerasi kueri non-kunci primer dengan kunci pengurutan

Setelah compact, data diurutkan berdasarkan kunci primer. Untuk mempercepat kueri pada kolom non-kunci primer, tentukan kunci pengurutan lalu compact ulang data tersebut.

Penting

Setelah Anda menentukan kunci pengurutan, Anda harus menulis ulang data dalam partisi untuk memastikan kinerja akselerasi. Hanya data yang telah ditulis ulang yang dapat dikueri, sedangkan data inkremental tidak dapat dikueri.

Tabel contoh:

USE lindorm_columnar;
CREATE TABLE orders (
  o_orderkey      INT    NOT NULL,
  o_custkey       INT,
  o_orderstatus   STRING,
  o_totalprice    DOUBLE,
  o_orderdate     STRING,
  o_orderpriority STRING,
  o_clerk         STRING,
  o_shippriority  INT,
  o_comment       STRING)
PARTITIONED BY (bucket(1024, o_orderkey))
TBLPROPERTIES (
  'primary-key'                          = 'o_orderkey',
  'read.scan-major-rewritten-files-only' = 'true');

Tetapkan kunci pengurutan:

ALTER TABLE orders WRITE ORDERED BY o_shippriority, o_totalprice;

Compact untuk menerapkan urutan pengurutan:

CALL lindorm_columnar.system.rewrite_data_files(table => 'orders');

Kueri menggunakan kunci pengurutan:

USE lindorm_columnar;
SELECT count(*) FROM orders WHERE o_shippriority = 0;
USE lindorm_columnar;
SELECT count(*) FROM orders WHERE o_shippriority = 0 AND o_totalprice > 999.9;