全部產品
Search
文件中心

Hologres:主鍵Primary Key

更新時間:Dec 11, 2024

為了確保資料表中每一條記錄的唯一性、資料的一致性和方便資料管理,您需要為表設定主關鍵字(Primary Key,簡稱主鍵或PK)。Hologres中主鍵與傳統資料庫主鍵特性一致,是表中記錄的唯一標識,代表了表資料的唯一性。因此被設定為主鍵的欄位是唯一的且是非空的,並且支援設定多個欄位為主鍵。本文為您介紹在Hologres中為表設定主鍵。

主鍵介紹

在Hologres中,系統會自動在底層儲存一個主鍵索引檔案,採用行存結構儲存,提供高速的KV(key- value)服務,索引檔案的Key為表的主鍵PK,Value為RID(Row Identified,原名為unique_id)和聚簇索引(Clustering Key)。RID每次UPSERT自動產生,單調遞增。主鍵索引檔案能夠實現高效的主鍵衝突判定並輔助資料檔案定位。假如為表設定了PK,那麼就可以通過PK在主鍵索引檔案中快速定位到RID和Clustering Key,再通過RID和Clustering Key定位到資料所在的檔案。

因此在Hologres中設定了主鍵,可以非常方便地支援即時數倉情境下的多種訴求:

  • 支援高效能的UPSERT或DELETE。

    Hologres具有傳統資料庫高效能Append Only類型的寫入特性外,還可以通過主鍵實現高效能的整行寫入更新、部分列寫入更新。在進行寫入更新時只需要根據主鍵更新,不需要全表掃描,從而達到高效能的UPSERT,同時也能保證資料的唯一性。

  • 支援高QPS的基於主鍵查詢。

    表格儲存體格式:列存、行存、行列共存一文中介紹:如果為表設定了PK,在基於PK的查詢情境中,就能快速根據主鍵定位到整行資料,提升查詢效能。尤其是當表設定為行存表時,主鍵預設為Clustering Key和Distribution Key,就能通過主鍵定位到資料檔案,實現超高QPS的主鍵點查,且延遲在毫秒級,適用於即時風控、即時推薦等線上應用情境。

使用建議

主鍵的設定盡量選擇含有實際業務意義的欄位,不建議將Serial類型的欄位設定為主鍵,因為Serial類型在寫入的時候是表鎖,導致寫入效能有損失,且隨著資料的增長,長度容易溢出。

使用限制

  • 被設定為主鍵的欄位是唯一且非空的列或者列組合,同時只能在一個語句裡設定多列為表的主鍵。

  • 最多支援32個列組成的聯合主鍵。

  • 不支援將FLOAT、DOUBLE、NUMERIC、ARRAY、JSON、JSONB、DATE及其他複雜資料類型的欄位設定為主鍵。Hologres從 V1.3.22及以上版本支援將Date類型欄位設為主鍵,如需將DATE類型欄位設為主鍵,請先查看您Hologres執行個體版本後視情況升級執行個體,詳情請參見執行個體配置執行個體升級

  • 行存表必須設定主鍵,行列共存表必須設定主鍵,列存表不要求有主鍵。

  • 不支援修改主鍵,如需修改主鍵請重建立表。

使用樣本

以下為Hologres V2.1版本起的文法樣本。如果您的執行個體為V2.0及以前版本,需要將DDL中的WITH (property = 'value')語句改為CALL set_table_property語句,詳情請參見CREATE TABLE

  • 建立普通列存表並指定一個主鍵。

    • V2.1版本起支援的建表文法:

      CREATE TABLE tbl_1 (
          id bigint NOT NULL,
          name text NOT NULL,
          age bigint NOT NULL,
          class text,
          reg_timestamp timestamptz NOT NULL,
          PRIMARY KEY (id)
      )
      WITH (
          orientation = 'column',
          distribution_key = 'id',
          clustering_key = 'age',
          event_time_column = 'reg_timestamp',
          bitmap_columns = 'name,class',
          dictionary_encoding_columns = 'class:auto'
      );
    • 所有版本支援的建表文法:

      BEGIN;
      CREATE TABLE tbl_1 (
       id bigint NOT NULL,
       name text NOT NULL,
       age bigint,
       class text,
       reg_timestamp timesatmptz, 
      PRIMARY KEY (id)
      );
      CALL set_table_property('tbl_1', 'orientation', 'column');
      CALL set_table_property('tbl_1', 'distribution_key', 'id');
      CALL set_table_property('tbl_1', 'clustering_key', 'age');
      CALL set_table_property('tbl_1', 'event_time_column', 'reg_timestamp');
      CALL set_table_property('tbl_1', 'bitmap_columns', 'name,class');
      CALL set_table_property('tbl_1', 'dictionary_encoding_columns', 'class:auto');
      COMMIT;
  • 建立一個普通列存表並指定兩個主鍵。

    • V2.1版本起支援的建表文法:

      CREATE TABLE tbl_1 (
          id bigint NOT NULL,
          name text NOT NULL,
          age bigint NOT NULL,
          class text NOT NULL,
          reg_timestamp timestamptz NOT NULL,
          PRIMARY KEY (id,age)
      )
      WITH (
          orientation = 'column',
          distribution_key = 'id',
          clustering_key = 'age',
          event_time_column = 'reg_timestamp',
          bitmap_columns = 'name,class',
          dictionary_encoding_columns = 'class:auto'
      );
    • 所有版本支援的建表文法:

      BEGIN;
      CREATE TABLE tbl_2 (
       id bigint NOT NULL,
       name text NOT NULL,
       age bigint NOT NULL,
       class text NOT NULL,
       reg_timestamp timestamptz NOT NULL,
      PRIMARY KEY (id,age)
      );
      CALL set_table_property('tbl_2', 'orientation', 'column');
      CALL set_table_property('tbl_2', 'distribution_key', 'id');
      CALL set_table_property('tbl_2', 'clustering_key', 'age');
      CALL set_table_property('tbl_2', 'event_time_column', 'reg_timestamp');
      CALL set_table_property('tbl_2', 'bitmap_columns', 'name,class');
      CALL set_table_property('tbl_2', 'dictionary_encoding_columns', 'class:auto');
      COMMIT;
  • 建立行存表並指定主鍵。

    • V2.1版本起支援的建表文法:

      CREATE TABLE public.tbl_row (
          id text NOT NULL,
          name text NOT NULL,
          class text,
          PRIMARY KEY (id)
      )
      WITH (
          orientation = 'row',
          distribution_key = 'id',
          clustering_key = 'id'
      );
    • 所有版本支援的建表文法:

      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;
  • 建立分區表並指定主鍵。

    • V2.1版本起支援的建表文法:

      BEGIN;
      CREATE TABLE public.tbl_parent(
        a text , 
        b int, 
        c timestamp, 
        d text,
        ds text,
        PRIMARY KEY (ds,b)
        )
       PARTITION BY LIST(ds)
       WITH ( orientation = 'column');
      CREATE TABLE public.tbl_child_1 PARTITION OF public.tbl_parent FOR VALUES IN('20221207');
      CREATE TABLE public.tbl_child_2 PARTITION OF public.tbl_parent FOR VALUES IN('20221208');
      COMMIT;
    • 所有版本支援的建表文法:

      BEGIN;
      CREATE TABLE public.tbl_parent(
        a text , 
        b int, 
        c timestamp, 
        d text,
        ds text,
        PRIMARY KEY (ds,b)
        )
        PARTITION BY LIST(ds);
      CALL set_table_property('public.tbl_parent', 'orientation', 'column');
      CREATE TABLE public.tbl_child_1 PARTITION OF public.tbl_parent FOR VALUES IN('20221207');
      CREATE TABLE public.tbl_child_2 PARTITION OF public.tbl_parent FOR VALUES IN('20221208');
      COMMIT;

相關文檔