全部产品
Search
文档中心

Hologres:Distribution key

更新时间:Jan 24, 2026

Jika tabel Anda sering memerlukan operasi GROUP BY atau JOIN, atau jika Anda ingin mencegah kesenjangan data, Anda dapat menetapkan distribution key saat membuat tabel. Distribution key yang sesuai mendistribusikan data secara merata ke seluruh node komputasi, sehingga secara signifikan meningkatkan performa komputasi dan kueri. Topik ini menjelaskan cara menetapkan distribution key untuk tabel di Hologres.

Pengenalan distribution key

Di Hologres, properti distribution key menentukan kebijakan distribusi data untuk suatu tabel. Sistem memastikan bahwa catatan dengan distribution key yang sama dialokasikan ke shard yang sama. Sintaks untuk menetapkan distribution key saat membuat tabel adalah sebagai berikut:

-- Sintaks yang didukung oleh Hologres V2.1 dan versi lebih baru
CREATE TABLE <table_name> (...) WITH (distribution_key = '[<columnName>[,...]]');

-- Sintaks yang didukung oleh semua versi
BEGIN;
CREATE TABLE <table_name> (...);
call set_table_property('<table_name>', 'distribution_key', '[<columnName>[,...]]');
COMMIT;

Tabel berikut menjelaskan parameter-parameter tersebut.

Parameter

Deskripsi

table_name

Nama tabel tempat Anda ingin menetapkan distribution key.

columnName

Nama bidang yang ingin Anda tetapkan sebagai distribution key.

Distribution key merupakan konsep kritis dalam sistem terdistribusi. Distribution key yang dikonfigurasi dengan tepat memberikan manfaat berikut:

  • Secara signifikan meningkatkan performa komputasi.

    Shard dapat melakukan komputasi secara paralel untuk meningkatkan performa komputasi.

  • Secara signifikan meningkatkan permintaan per detik (QPS).

    Saat Anda menggunakan distribution key sebagai kondisi filter, Hologres hanya perlu memindai shard yang relevan. Jika tidak, Hologres harus memindai semua shard, yang mengurangi QPS.

  • Secara signifikan meningkatkan performa JOIN.

    Jika dua tabel berada dalam kelompok tabel yang sama dan bidang JOIN-nya merupakan distribution key, distribusi data memastikan bahwa data yang saling berkaitan dari kedua tabel berada di shard yang sama. Hal ini memungkinkan Local Join dilakukan pada data di dalam setiap node, yang secara signifikan meningkatkan efisiensi eksekusi.

Saran penggunaan

Ikuti prinsip-prinsip berikut saat menetapkan distribution key:

  • Pilih bidang dengan distribusi data yang merata sebagai distribution key. Jika tidak, kesenjangan data dapat menyebabkan ketidakseimbangan beban dan mengurangi efisiensi kueri. Untuk informasi lebih lanjut tentang cara memeriksa kesenjangan data, lihat Lihat hubungan skew worker.

  • Pilih bidang yang sering digunakan dalam klausa GROUP BY sebagai distribution key.

  • Dalam skenario JOIN, tetapkan bidang JOIN sebagai distribution key untuk mengaktifkan Local Join dan menghindari data shuffle. Tabel-tabel yang Anda gabungkan harus berada dalam kelompok tabel yang sama.

  • Jangan menetapkan terlalu banyak bidang sebagai distribution key. Kami menyarankan agar Anda menggunakan tidak lebih dari dua bidang. Jika Anda menetapkan beberapa bidang sebagai distribution key, data shuffle dapat terjadi jika kueri tidak mencakup semua bidang tersebut. Hindari menggunakan composite distribution key di mana nilai kolomnya identik. Hal ini menyebabkan semua data didistribusikan ke satu shard saja, sehingga menimbulkan kesenjangan data.

  • Anda dapat menetapkan satu atau beberapa kolom sebagai distribution key. Jika Anda menentukan beberapa kolom, pisahkan dengan koma (,). Urutan kolom tidak memengaruhi tata letak data atau performa kueri saat Anda menentukan beberapa kolom sebagai distribution key.

  • Jika sebuah tabel memiliki primary key (PK), distribution key harus berupa PK atau subset dari bidang PK. Distribution key tidak boleh kosong. Anda harus menentukan setidaknya satu kolom. Jika Anda tidak menentukan distribution key, PK akan digunakan sebagai distribution key secara default.

Batasan

  • Anda harus menetapkan distribution key saat membuat tabel. Untuk mengubah distribution key, Anda harus membuat ulang tabel dan mengimpor data.

  • Anda tidak dapat mengubah nilai di kolom Distribution Key. Untuk mengubahnya, Anda harus membuat ulang tabel.

  • Anda tidak dapat menetapkan bidang bertipe data Float, Double, Numeric, Array, JSON, atau tipe data kompleks lainnya sebagai distribution key.

  • Jika sebuah tabel tidak memiliki PK, distribution key dapat kosong, artinya tidak ada kolom yang ditentukan. Jika distribution key kosong, data akan diacak dan didistribusikan ke shard yang berbeda. Mulai dari Hologres V1.3.28, distribution key tidak boleh kosong. Contoh berikut menunjukkan sintaks yang tidak lagi didukung.

    --Mulai dari V1.3.28, sintaks ini dilarang.
    CALL SET_TABLE_PROPERTY('<tablename>', 'distribution_key', '');
  • Jika kolom distribution key berisi nilai null, nilai tersebut diperlakukan sebagai string kosong ("") untuk keperluan penghashan.

Prinsip teknis

Distribution Key menentukan kebijakan distribusi untuk suatu tabel. Kebijakan yang tepat bergantung pada skenario bisnis.

Mengatur kunci distribusi

Setelah Anda menetapkan distribution key untuk suatu tabel, data dialokasikan ke setiap shard berdasarkan distribution key tersebut. Algoritmanya adalah Hash(distribution_key)%shard_count. Hasil perhitungan ini menentukan shard tujuan untuk suatu catatan. Sistem memastikan bahwa semua catatan dengan distribution key yang sama dialokasikan ke shard yang sama. Contoh berikut menunjukkan cara menetapkan distribution key.

  • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

    --Tetapkan kolom a sebagai distribution key. Sistem melakukan operasi hash pada nilai di kolom a lalu operasi modulo. Rumusnya adalah hash(a) % shard_count = shard_id. Data dengan hasil yang sama didistribusikan ke shard yang sama.
    CREATE TABLE tbl (
        a int NOT NULL,
        b text NOT NULL
    )
    WITH (
        distribution_key = 'a'
    );
    
    --Tetapkan kolom a dan b sebagai distribution key. Sistem melakukan operasi hash pada nilai di kolom a dan b lalu operasi modulo. Rumusnya adalah hash(a,b) % shard_count = shard_id. Data dengan hasil yang sama didistribusikan ke shard yang sama.
    CREATE TABLE tbl (
        a int NOT NULL,
        b text NOT NULL
    )
    WITH (
        distribution_key = 'a,b'
    );
  • Sintaks untuk membuat tabel (didukung oleh semua versi):

    --Tetapkan kolom a sebagai distribution key. Sistem melakukan operasi hash pada nilai di kolom a lalu operasi modulo. Rumusnya adalah hash(a) % shard_count = shard_id. Data dengan hasil yang sama didistribusikan ke shard yang sama.
    begin;
    create table tbl (
    a int not null,
    b text not null
    );
    call set_table_property('tbl', 'distribution_key', 'a');
    commit;
    
    --Tetapkan kolom a dan b sebagai distribution key. Sistem melakukan operasi hash pada nilai di kolom a dan b lalu operasi modulo. Rumusnya adalah hash(a,b) % shard_count = shard_id. Data dengan hasil yang sama didistribusikan ke shard yang sama.
    begin;
    create table tbl (
      a int not null,
      b text not null
    );
    call set_table_property('tbl', 'distribution_key', 'a,b');
    commit;
                                

Gambar berikut menunjukkan distribusi data.设置distribution keySaat menetapkan distribution key, pastikan data di bidang yang ditentukan terdistribusi secara merata. Jumlah shard di Hologres berkaitan dengan jumlah node pekerja. Untuk informasi lebih lanjut, lihat Istilah. Jika Anda menetapkan bidang dengan distribusi data yang tidak merata sebagai distribution key, data akan terkonsentrasi di beberapa shard saja. Hal ini menyebabkan sebagian besar komputasi dilakukan oleh beberapa node pekerja, yang dapat menimbulkan efek long-tail dan mengurangi efisiensi kueri. Untuk informasi lebih lanjut tentang cara memecahkan masalah dan menangani kesenjangan data, lihat Lihat hubungan skew worker.

Tidak menetapkan distribution key

Jika Anda tidak menetapkan Distribution Key, data didistribusikan secara acak ke semua shard. Artinya, catatan yang identik dapat disimpan di shard yang sama atau di shard yang berbeda. Berikut adalah contohnya.

--Jangan tetapkan distribution key.
begin;
create table tbl (
a int not null,
b text not null
);
commit;

Gambar berikut menunjukkan distribusi data.不设置distribution key

Menetapkan distribution key untuk skenario agregasi GROUP BY

Dalam skenario agregasi GROUP BY, jika bidang yang dikelompokkan bukan distribution key, data harus didistribusikan ulang selama komputasi. Oleh karena itu, Anda dapat menetapkan bidang yang sering digunakan dalam klausa GROUP BY sebagai distribution key. Dengan demikian, data sudah teragregasi di dalam shard, yang mengurangi redistribusi data antar shard dan meningkatkan performa kueri. Contoh berikut menunjukkan cara menetapkan distribution key untuk skenario agregasi GROUP BY.

  • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

    CREATE TABLE agg_tbl (
        a int NOT NULL,
        b int NOT NULL
    )
    WITH (
        distribution_key = 'a'
    );
    
    --Contoh kueri: Lakukan kueri agregasi pada kolom a.
    select a,sum(b) from agg_tbl group by a;
  • Sintaks untuk membuat tabel (didukung oleh semua versi):

    begin;
    create table agg_tbl (
    a int not null,
    b int not null
    );
    call set_table_property('agg_tbl', 'distribution_key', 'a');
    commit;
    
    --Contoh kueri: Lakukan kueri agregasi pada kolom a.
    select a,sum(b) from agg_tbl group by a;

Lihat rencana eksekusi dengan menjalankan pernyataan EXPLAIN SQL. Hasil rencana eksekusi tidak mengandung operator redistribution, yang menunjukkan bahwa data tidak didistribusikan ulang.QUERY PLAN

Menetapkan distribution key untuk skenario join dua tabel

  • Tetapkan bidang JOIN dari dua tabel sebagai distribution key

    Dalam skenario join dua tabel, jika Anda menetapkan bidang JOIN masing-masing tabel sebagai distribution key-nya, data dengan nilai bidang JOIN yang sama akan didistribusikan ke shard yang sama. Hal ini memungkinkan Local Join dan mempercepat kueri. Contoh berikut menunjukkan cara menetapkan bidang JOIN sebagai distribution key.

    • Pernyataan DDL untuk membuat tabel.

      • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

        --tbl1 didistribusikan berdasarkan kolom a, dan tbl2 didistribusikan berdasarkan kolom c. Saat tbl1 dan tbl2 di-join dengan kondisi a=c, data yang bersesuaian didistribusikan di shard yang sama. Kueri ini dapat dipercepat dengan Local Join.
        BEGIN;
        CREATE TABLE tbl1 (
            a int NOT NULL,
            b text NOT NULL
        )
        WITH (
            distribution_key = 'a'
        );
        CREATE TABLE tbl2 (
            c int NOT NULL,
            d text NOT NULL
        )
        WITH (
            distribution_key = 'c'
        );
        COMMIT;
      • Sintaks untuk membuat tabel (didukung oleh semua versi):

        --tbl1 didistribusikan berdasarkan kolom a, dan tbl2 didistribusikan berdasarkan kolom c. Saat tbl1 dan tbl2 di-join dengan kondisi a=c, data yang bersesuaian didistribusikan di shard yang sama. Kueri ini dapat dipercepat dengan Local Join.
        begin;
        create table tbl1(
        a int not null,
        b text not null
        );
        call set_table_property('tbl1', 'distribution_key', 'a');
        
        create table tbl2(
        c int not null,
        d text not null
        );
        call set_table_property('tbl2', 'distribution_key', 'c');
        commit;
                                            
    • Pernyataan kueri.

      select * from tbl1  join tbl2 on tbl1.a=tbl2.c;

    Gambar berikut menunjukkan distribusi data.两表关联joinLihat rencana eksekusi dengan menjalankan pernyataan `EXPLAIN SQL`. Hasil rencana eksekusi tidak mengandung operator redistribution, yang menunjukkan bahwa data tidak didistribusikan ulang.join执行计划

  • Saat bidang JOIN tidak digunakan sebagai distribution key untuk kedua tabel

    Dalam skenario join dua tabel, jika bidang `JOIN` masing-masing tabel tidak ditetapkan sebagai distribution key-nya, data akan di-shuffle ke seluruh shard selama kueri. Rencana eksekusi menentukan apakah akan melakukan shuffle atau broadcast berdasarkan ukuran kedua tabel. Pada contoh berikut, distribution key untuk tbl1 adalah bidang a, dan distribution key untuk tbl2 adalah bidang d. Kondisi `JOIN`-nya adalah a=c. Data di bidang c di-shuffle ke setiap shard, yang mengurangi efisiensi kueri.

    • Pernyataan DDL untuk membuat tabel.

      • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

        BEGIN;
        CREATE TABLE tbl1 (
            a int NOT NULL,
            b text NOT NULL
        )
        WITH (
            distribution_key = 'a'
        );
        CREATE TABLE tbl2 (
            c int NOT NULL,
            d text NOT NULL
        )
        WITH (
            distribution_key = 'd'
        );
        COMMIT;
      • Sintaks untuk membuat tabel (didukung oleh semua versi):

        begin;
        create table tbl1(
        a int not null,
        b text not null
        );
        call set_table_property('tbl1', 'distribution_key', 'a');
        create table tbl2(
        c int not null,
        d text not null
        );
        call set_table_property('tbl2', 'distribution_key', 'd');
        commit;
    • Pernyataan kueri.

      select * from tbl1  join tbl2 on tbl1.a=tbl2.c;

    Gambar berikut menunjukkan distribusi data.2个表join且distribution key不一致Lihat rencana eksekusi dengan menjalankan pernyataan EXPLAIN SQL. Hasil rencana eksekusi memuat operator redistribution, yang menunjukkan bahwa data didistribusikan ulang karena distri­bution key tidak dikonfigurasi dengan benar. Pertimbangkan untuk menyetel ulang distribution key.distribution key执行计划

Menetapkan distribution key untuk skenario join multi-tabel

Skenario join multi-tabel bersifat kompleks. Anda dapat mengikuti prinsip-prinsip berikut:

  • Jika bidang JOIN semua tabel sama, tetapkan bidang JOIN masing-masing tabel sebagai distribution key-nya.

  • Jika bidang JOIN tabel-tabel tersebut berbeda, utamakan JOIN antar tabel besar. Tetapkan bidang JOIN tabel besar sebagai distribution key-nya.

Contoh berikut menjelaskan beberapa kasus. Topik ini menggunakan join tiga tabel sebagai contoh. Prinsip yang sama berlaku untuk join yang melibatkan lebih dari tiga tabel.

  • Kasus 1: Bidang JOIN ketiga tabel sama

    Dalam skenario join tiga tabel di mana bidang JOIN-nya sama, Anda cukup menetapkan bidang JOIN masing-masing tabel sebagai distribution key-nya untuk mengaktifkan Local Join.

    • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

      BEGIN;
      CREATE TABLE join_tbl1 (
          a int NOT NULL,
          b text NOT NULL
      )
      WITH (
          distribution_key = 'a'
      );
      CREATE TABLE join_tbl2 (
          a int NOT NULL,
          d text NOT NULL,
          e text NOT NULL
      )
      WITH (
          distribution_key = 'a'
      );
      CREATE TABLE join_tbl3 (
          a int NOT NULL,
          e text NOT NULL,
          f text NOT NULL,
          g text NOT NULL
      )
      WITH (
          distribution_key = 'a'
      );
      COMMIT;
      
      --Kueri join 3 tabel
      SELECT * FROM join_tbl1
      INNER JOIN join_tbl2 ON join_tbl2.a = join_tbl1.a
      INNER JOIN join_tbl3 ON join_tbl2.a = join_tbl3.a;
    • Sintaks untuk membuat tabel (didukung oleh semua versi):

      begin;
      create table join_tbl1(
      a int not null,
      b text not null
      );
      call set_table_property('join_tbl1', 'distribution_key', 'a');
      
      create table join_tbl2(
      a int not null,
      d text not null,
      e text not null
      );
      call set_table_property('join_tbl2', 'distribution_key', 'a');
      
      create table join_tbl3(
      a int not null,
      e text not null,
      f text not null,
      g text not null
      );
      call set_table_property('join_tbl3', 'distribution_key', 'a');
      commit;
      
      --Kueri join 3 tabel
      SELECT * FROM join_tbl1
      INNER JOIN join_tbl2 ON join_tbl2.a = join_tbl1.a
      INNER JOIN join_tbl3 ON join_tbl2.a = join_tbl3.a;

    Lihat rencana eksekusi dengan menjalankan pernyataan EXPLAIN SQL. Hasil rencana eksekusi menunjukkan hal berikut:

    • Rencana tidak mengandung operator redistribution, yang menunjukkan bahwa data tidak didistribusikan ulang dan Local Join dilakukan.

    • Operator exchange menunjukkan bahwa data diagregasi dari tingkat file ke tingkat shard, sehingga hanya data dari shard yang bersesuaian yang diperlukan—meningkatkan efisiensi kueri.

    3表join

  • Kasus 2: Bidang JOIN ketiga tabel berbeda

    Dalam beberapa skenario bisnis, bidang JOIN dalam join multi-tabel mungkin berbeda. Dalam kasus ini, Anda dapat menetapkan distribution key berdasarkan prinsip berikut:

    • Prinsip optimasi utama adalah mengutamakan JOIN antar tabel besar dengan menetapkan bidang JOIN-nya sebagai distribution key. Mengoptimalkan tabel kecil kurang penting karena jumlah datanya sedikit.

    • Jika jumlah data tabel-tabel tersebut kira-kira sama, Anda dapat menetapkan bidang JOIN yang sering digunakan dalam klausa GROUP BY sebagai distribution key.

    Pada contoh berikut, tiga tabel di-join, tetapi bidang JOIN-nya tidak semuanya sama. Dalam kasus ini, Anda harus menetapkan distribution key untuk mengoptimalkan join yang melibatkan tabel terbesar. Tabel join_tbl_1 memiliki 10 juta catatan, sedangkan join_tbl_2 dan join_tbl_3 masing-masing memiliki 1 juta catatan. Sasaran utama optimasi adalah join_tbl_1.

    • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

      BEGIN;
      -- join_tbl_1 berisi 10 juta catatan.
      CREATE TABLE join_tbl_1 (
          a int NOT NULL,
          b text NOT NULL
      )
      WITH (
          distribution_key = 'a'
      );
      -- join_tbl_2 berisi 1 juta catatan.
      CREATE TABLE join_tbl_2 (
          a int NOT NULL,
          d text NOT NULL,
          e text NOT NULL
      )
      WITH (
          distribution_key = 'a'
      );
      -- join_tbl_3 berisi 1 juta catatan.
      CREATE TABLE join_tbl_3 (
          a int NOT NULL,
          e text NOT NULL,
          f text NOT NULL,
          g text NOT NULL
      );
       WITH (
           distribution_key = 'a'
       );
      COMMIT;
      
      --Saat kunci JOIN berbeda, pilih kunci JOIN dari tabel terbesar sebagai distribution key.
      SELECT * FROM join_tbl_1
      INNER JOIN join_tbl_2 ON join_tbl_2.a = join_tbl_1.a
      INNER JOIN join_tbl_3 ON join_tbl_2.d = join_tbl_3.f;
    • Sintaks untuk membuat tabel (didukung oleh semua versi):

      begin;
      --join_tbl_1 berisi 10 juta catatan.
      create table join_tbl_1(
      a int not null,
      b text not null
      );
      call set_table_property('join_tbl_1', 'distribution_key', 'a');
      
      --join_tbl_2 berisi 1 juta catatan.
      create table join_tbl_2(
      a int not null,
      d text not null,
      e text not null
      );
      call set_table_property('join_tbl_2', 'distribution_key', 'a');
      
      --join_tbl_3 berisi 1 juta catatan.
      create table join_tbl_3(
      a int not null,
      e text not null,
      f text not null,
      g text not null
      );
      --call set_table_property('join_tbl_3', 'distribution_key', 'a');
      commit;
      
      --Saat kunci JOIN berbeda, pilih kunci JOIN dari tabel terbesar sebagai distribution key.
      SELECT * FROM join_tbl_1
      INNER JOIN join_tbl_2 ON join_tbl_2.a = join_tbl_1.a
      INNER JOIN join_tbl_3 ON join_tbl_2.d = join_tbl_3.f;

    Lihat rencana eksekusi dengan menjalankan pernyataan EXPLAIN SQL. Rencana eksekusi menunjukkan hal berikut:

    • Rencana mengandung operator redistribution antara tabel join_tbl_2 dan join_tbl_3. Hal ini disebabkan join_tbl_3 merupakan tabel kecil, dan bidang `JOIN`-nya berbeda dari distribution key-nya, sehingga datanya harus didistribusikan ulang.

    • Rencana tidak mengandung operator redistribution antara tabel join_tbl_1 dan join_tbl_2 karena kolom `JOIN` pada masing-masing tabel telah ditetapkan sebagai distribution key. Dengan demikian, Local Join dapat dilakukan tanpa redistribusi data.

    3表join执行计划

Contoh penggunaan

  • Sintaks untuk membuat tabel (didukung oleh Hologres V2.1 dan versi lebih baru):

    --Tetapkan distribution key untuk satu tabel.
    CREATE TABLE tbl (
        a int NOT NULL,
        b text NOT NULL
    )
    WITH (
        distribution_key = 'a'
    );
    
    --Tetapkan beberapa distribution key.
    CREATE TABLE tbl (
        a int NOT NULL,
        b text NOT NULL
    )
    WITH (
        distribution_key = 'a,b'
    );
    
    
    --Dalam skenario JOIN, tetapkan kunci JOIN sebagai distribution key.
    BEGIN;
    CREATE TABLE tbl1 (
        a int NOT NULL,
        b text NOT NULL
    )
    WITH (
        distribution_key = 'a'
    );
    CREATE TABLE tbl2 (
        c int NOT NULL,
        d text NOT NULL
    )
    WITH (
        distribution_key = 'c'
    );
    COMMIT;
    
    SELECT b, count(*) FROM tbl1 JOIN tbl2 ON tbl1.a = tbl2.c GROUP BY b;
  • Sintaks untuk membuat tabel (didukung oleh semua versi):

    --Tetapkan satu distribution key.
    begin;
    create table tbl (a int not null, b text not null);
    call set_table_property('tbl', 'distribution_key', 'a');
    commit;
    
    --Tetapkan beberapa distribution key.
    begin;
    create table tbl (a int not null, b text not null);
    call set_table_property('tbl', 'distribution_key', 'a,b');
    commit;
    
    --Dalam skenario JOIN, tetapkan kunci JOIN sebagai distribution key.
    begin;
    create table tbl1(a int not null, b text not null);
    call set_table_property('tbl1', 'distribution_key', 'a');
    create table tbl2(c int not null, d text not null);
    call set_table_property('tbl2', 'distribution_key', 'c');
    commit;
    
    select b, count(*) from tbl1 join tbl2 on tbl1.a = tbl2.c group by b;

Referensi