All Products
Search
Document Center

ApsaraDB for HBase:Cara mendesain Rowkey

Last Updated:Mar 29, 2026

Rowkey adalah pengidentifikasi unik untuk setiap baris dalam tabel HBase. Rowkey menentukan cara data disimpan, dipartisi, dan diakses. Rancang rowkey dengan cermat sebelum menulis data dalam skala besar.

Topik ini mencakup lima pertimbangan desain, lengkap dengan kompromi dan contoh untuk data log serta data transaksi.

Cara kerja rowkey

Metode kueri

HBase mendukung dua metode kueri, masing-masing memiliki batasan berbeda terhadap desain rowkey:

MethodDescriptionConstraint
GETMencari satu baris berdasarkan rowkey lengkapnyaSemua bidang yang membentuk rowkey harus diketahui
ScanMembaca rentang baris antara kunci awal dan kunci akhirHanya rentang berbasis awalan (prefix) yang didukung

Batasan awalan untuk scan: Scan mencocokkan baris yang dimulai dengan awalan tertentu, tetapi tidak dapat melakukan kueri berdasarkan akhiran (suffix) atau mencocokkan nilai di tengah rowkey. Sebagai contoh, jika rowkey berupa kata kamus, scan dapat menemukan semua kata yang diawali dengan pre, tetapi tidak dapat menemukan kata yang diakhiri dengan ing.

Untuk kueri yang tidak dapat dinyatakan sebagai scan berbasis awalan, gunakan salah satu pendekatan berikut:

  • Buat tabel indeks dengan struktur kunci terbalik

  • Terapkan filter sisi server untuk membuang baris yang tidak diinginkan

  • Gunakan indeks sekunder

Keunikan dan versi rowkey

Baris dengan rowkey yang sama dianggap sebagai satu catatan dengan beberapa versi. Secara default, GET mengembalikan versi terbaru. Rowkey harus unik kecuali Anda sengaja menggunakan Multi-Version Concurrency Control (MVCC).

Perlakukan rowkey seperti primary key dalam database. Rowkey dapat berupa satu bidang atau gabungan dari beberapa bidang:

  • [user_id] — satu catatan per pengguna

  • [user_id][order_id] — beberapa catatan per pengguna

Pertimbangan desain

Distribusi data: hindari hot spot

HBase mendistribusikan baris ke Region server berdasarkan rentang rowkey (urutan leksikografis). Jika banyak operasi tulis memiliki awalan umum—misalnya, kunci yang diawali timestamp seperti 2024-01-01T00:00:01—semua tulisan akan menuju Region server yang sama. Hal ini menciptakan hot spot yang menurunkan throughput tulis dan membuat server lain menganggur.

Gunakan salah satu teknik berikut untuk menyebarkan tulisan ke berbagai Region server:

Salting dengan awalan hash

Tambahkan beberapa karakter pertama dari Hash MD5 ke awal rowkey. Karena hash bersifat deterministik, input yang sama selalu menghasilkan awalan yang sama, sehingga pembacaan tetap efisien.

[md5(user_id).subStr(0, 4)][user_id][order_id]

Kompromi: baris untuk pengguna yang sama tersebar di Region berbeda. Memindai rentang untuk satu pengguna memerlukan beberapa GET terarah atau scan dengan filter.

Membalik kunci

Balikkan bidang awalan dengan kardinalitas tinggi. Misalnya, membalik user ID yang meningkat seiring waktu akan mengacak byte awalnya.

[reverse(user_id)][order_id]

Kompromi: urutan alami hilang, sehingga scan rentang pada bidang yang dibalik tidak lagi bermakna.

Pengelompokan (bucketing) dengan operasi modulo

Tetapkan setiap baris ke bucket menggunakan operasi modulo, lalu tambahkan nomor bucket di awal. Pendekatan ini efektif untuk data deret waktu dengan timestamp yang meningkat secara monoton.

long bucket = timestamp % numBuckets;
[bucket][timestamp][hostname][log_event]

Kompromi: untuk mengambil semua data dalam rentang waktu tertentu, Anda harus memindai semua rentang numBuckets dan menggabungkan hasilnya.

Menambahkan akhiran acak

Tambahkan bilangan acak untuk mendistribusikan tulisan ke beberapa baris.

[user_id][order_id][random(100)]

Kompromi: membaca catatan tertentu memerlukan pengetahuan tentang akhiran acak tersebut. Pencarian titik (point lookup) menjadi tidak praktis tanpa indeks.

Cara memilih: Jika Anda perlu memindai baris yang didistribusikan (bukan hanya mencari catatan individual), gunakan hashing daripada akhiran acak—hashing bersifat deterministik, sehingga pembacaan dapat diarahkan secara efisien.

Panjang rowkey: buat sesingkat mungkin

Rowkey disimpan bersama setiap nilai kolom di HBase. Rowkey yang panjang akan melipatgandakan overhead penyimpanan di setiap kolom pada setiap baris. Buat rowkey sesingkat mungkin:

  • Ganti string dengan tipe numerik. Tipe long memakan 8 byte; string "2015122410" memakan 10 byte, dan string MD5 memakan 32 byte. Gunakan Long(2015122410) daripada "2015122410".

  • Gunakan kode daripada nama lengkap. Misalnya, gunakan tb daripada "Taobao".

Kejelasan batas bidang: cegah pencocokan parsial

Saat rowkey menggabungkan beberapa bidang tanpa pembatas, rentang scan dapat mengembalikan baris tambahan. Misalnya, jika rowkey berupa [column1][column2][column3] dan Anda memindai dari host1 hingga host2, baris host12... juga termasuk dalam rentang tersebut.

Dua pendekatan berikut mencegah hal ini:

Fixed-length padding: Isi setiap bidang hingga lebar tetap agar batasnya tidak ambigu.

[rpad(column1, 'x', 20)][column2]

Delimiter: Pisahkan bidang dengan karakter pembatas.

[column1][_][column2]

Padding panjang tetap lebih efisien untuk scan. Pembatas lebih mudah dibaca.

Urutan menurun: gunakan timestamp terbalik

Secara default, scan HBase mengembalikan baris dalam urutan kunci menaik. Jika Anda membutuhkan entri terbaru lebih dahulu, tersedia dua opsi:

Opsi 1: API scan terbalik (scan.setReverse(true))

Lebih mudah diimplementasikan, tetapi scan terbalik berkinerja lebih buruk daripada scan maju. Gunakan ini jika urutan menurun hanya kadang-kadang diperlukan.

Opsi 2: Timestamp terbalik dalam rowkey

Simpan Long.MAX_VALUE - timestamp daripada timestamp mentah. Ini membalik urutan pengurutan alami sehingga entri terbaru muncul lebih dahulu dalam scan maju.

timestamp = Long.MAX_VALUE - timestamp;
[hostname][log_event][timestamp]

Gunakan ini jika urutan menurun merupakan pola akses utama dan kinerja scan sangat penting.

Contoh desain

Desain rowkey yang tepat bergantung pada pola akses utama Anda. Dataset yang sama dapat memerlukan desain berbeda tergantung cara pengkueriannya. Contoh berikut menunjukkan bagaimana pola akses mendorong keputusan desain.

Data log dan data deret waktu

Elemen data meliputi: hostname, log_event, timestamp.

Access patternRowkey designNotes
Kueri metrik untuk host dalam rentang waktu[hostname][log_event][timestamp]Efisien untuk scan rentang per host. Dapat menimbulkan hot spot jika satu host mendominasi tulisan
Kueri catatan terbaru untuk host[hostname][log_event][Long.MAX_VALUE - timestamp]Timestamp terbalik menempatkan entri terbaru di awal dalam scan maju
Distribusikan tulisan secara merata sepanjang waktu (volume data besar atau tidak ada host dominan)[bucket][timestamp][hostname][log_event] dengan bucket = timestamp % numBucketsMemerlukan pemindaian semua rentang bucket untuk menggabungkan hasil dalam rentang waktu tertentu

Cara memilih: Mulailah dengan [hostname][log_event][timestamp] jika kueri rentang per host merupakan kasus penggunaan utama. Beralihlah ke pola bucket jika muncul hot spot tulis atau jika kueri rentang waktu mencakup banyak host.

Data transaksi

Sebuah transaksi melibatkan tiga peran: pembeli, penjual, dan nomor pesanan. Pola akses berbeda memerlukan desain rowkey berbeda—dan sering kali memerlukan beberapa tabel.

Access patternTableRowkey design
Kueri pesanan penjual dalam rentang waktuSeller table[seller_id][timestamp][order_number]
Kueri pesanan pembeli dalam rentang waktuBuyer table[buyer_id][timestamp][order_number]
Cari pesanan berdasarkan nomor pesananIndex table[order_number]

Rancang ketiga tabel tersebut untuk mencakup ketiga pola akses. Gunakan tabel indeks untuk mencari order_number, lalu kueri tabel pembeli atau penjual dengan nilai tersebut.

Langkah selanjutnya

  • Ikhtisar model data HBase

  • Secondary indexes di HBase

  • Tuning kinerja untuk tabel HBase