為了確保資料表中每一條記錄的唯一性、資料的一致性和方便資料管理,您需要為表設定主關鍵字(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類型在寫入的時候是表鎖,導致寫入效能有損失,且隨著資料的增長,長度容易溢出。
使用限制
使用樣本
以下為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;
相關文檔
根據業務查詢情境設定合適的表屬性指南,請參見情境化建表調優指南。
Key/Value查詢情境建表和查詢最佳實務,請參見Key/Value查詢情境最佳實務。