CREATE TABLE を使用して、Hologres 内のテーブルのストレージレイアウトを定義します。作成時に適切なストレージモード、分散キー、およびインデックスを設定することが重要です。これらのプロパティのほとんどは、テーブル作成後に変更することはできません。
前提条件
開始する前に、以下を確認してください。
-
ターゲットデータベースへの接続 — クエリの実行には HoloWeb の使用を推奨
クイックスタート
この例では、CREATE TABLE WITH 構文 (Hologres V2.1 以降で利用可能) を使用して、トランザクション詳細テーブルを作成します。階層型命名規則を使用し、複数のフィールドを定義し、メタデータコメントを含んでいます。
BEGIN;
-- トランザクション詳細のファクトテーブルを作成します。
-- public スキーマを使用し、階層型命名規則 (dwd_xxx) に従います。
CREATE TABLE IF NOT EXISTS public.dwd_trade_orders (
order_id BIGINT NOT NULL,
shop_id INT NOT NULL,
user_id TEXT NOT NULL,
order_amount NUMERIC(12, 2) DEFAULT 0.00,
payment NUMERIC(12, 2) DEFAULT 0.00,
payment_type INT DEFAULT 0, -- 0: 未払い, 1: Alipay, 2: WeChat Pay, 3: クレジットカード
is_delivered BOOLEAN DEFAULT false,
dt TEXT NOT NULL, -- データタイムスタンプ、YYYYMMDD 形式
order_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (order_id)
)
WITH (
orientation = 'column', -- 列指向: 大規模データセットでの OLAP 集約に最適
distribution_key = 'order_id', -- 均等な分散のために order_id でデータをシャーディング
clustering_key = 'order_time:asc', -- ファイル内で時間順にデータをソートし、範囲クエリを高速化
event_time_column = 'order_time', -- 時間範囲フィルターのファイルレベルのクリッピングを有効化
bitmap_columns = 'shop_id,payment_type,is_delivered', -- 低カーディナリティ列での等価フィルターを高速化
dictionary_encoding_columns = 'user_id:auto' -- 文字列型列での GROUP BY および FILTER を高速化
);
-- メタデータコメントを追加します。
COMMENT ON TABLE public.dwd_trade_orders IS 'トランザクション注文詳細の基本ファクトテーブル。';
COMMENT ON COLUMN public.dwd_trade_orders.order_id IS '注文の一意の識別子。';
COMMENT ON COLUMN public.dwd_trade_orders.shop_id IS '店舗の一意の ID。';
COMMENT ON COLUMN public.dwd_trade_orders.user_id IS '購入者の ID。';
COMMENT ON COLUMN public.dwd_trade_orders.dt IS 'データタイムスタンプ、YYYYMMDD 形式。';
COMMENT ON COLUMN public.dwd_trade_orders.order_time IS '注文が作成された正確なタイムスタンプ。';
COMMIT;
テーブルスキーマの表示
次のクエリを実行して、テーブルのデータ定義言語 (DDL) 文を取得します。
SELECT hg_dump_script('public.dwd_trade_orders');
データの挿入
Hologres は標準のデータ操作言語 (DML) 構文と互換性があります。次の文は、10 行のサンプルデータを挿入します。
INSERT INTO public.dwd_trade_orders
(order_id, shop_id, user_id, order_amount, payment, payment_type, is_delivered, dt, order_time)
VALUES
(50001, 101, 'U678', 299.00, 280.00, 1, true, '20231101', '2023-11-01 10:00:01+08'),
(50002, 102, 'U992', 59.00, 59.00, 2, false, '20231101', '2023-11-01 10:05:12+08'),
(50003, 101, 'U441', 150.00, 145.00, 1, true, '20231101', '2023-11-01 10:10:45+08'),
(50004, 105, 'U219', 888.00, 888.00, 3, true, '20231101', '2023-11-01 10:20:11+08'),
(50005, 102, 'U883', 35.00, 30.00, 1, false, '20231101', '2023-11-01 10:32:00+08'),
(50006, 110, 'U007', 120.50, 120.50, 2, true, '20231101', '2023-11-01 10:45:33+08'),
(50007, 101, 'U321', 210.00, 210.00, 1, true, '20231101', '2023-11-01 11:02:19+08'),
(50008, 108, 'U556', 45.00, 45.00, 2, false, '20231101', '2023-11-01 11:15:04+08'),
(50009, 101, 'U112', 300.00, 290.00, 3, true, '20231101', '2023-11-01 11:25:55+08'),
(50010, 105, 'U449', 99.90, 99.90, 1, true, '20231101', '2023-11-01 11:40:22+08');
データのクエリ
-- 店舗ごとの合計取引額を計算し、降順でソートします。
SELECT
shop_id,
COUNT(1) AS total_orders,
SUM(payment) AS total_payment
FROM public.dwd_trade_orders
GROUP BY shop_id
ORDER BY total_payment DESC;
期待される出力:
shop_id total_orders total_payment
105 2 987.90
101 4 925.00
110 1 120.50
102 1 59.00
108 1 45.00
構文
CREATE TABLE 構文
Hologres は、テーブルプロパティとコメントを定義するために 2 つの構文をサポートしています。
標準構文 (Hologres V2.1 以降で推奨)
WITH キーワードを使用してプロパティをインラインで定義します。この構文はよりコンパクトで、パフォーマンスも向上します。
BEGIN;
CREATE TABLE [IF NOT EXISTS] [schema_name.]table_name (
{
column_name column_type [column_constraints, [...]]
| table_constraints
[,...]
}
)
[WITH (
property = 'value'
[, ...]
)];
[COMMENT ON COLUMN <[schema_name.]tablename.column> IS '<value>';]
[COMMENT ON TABLE <[schema_name.]tablename> IS '<value>';]
COMMIT;
互換構文 (すべてのバージョンでサポート)
CALL set_table_property を使用してプロパティを設定し、COMMENT を使用してコメントを追加します。すべての文は、CREATE TABLE と同じ BEGIN...COMMIT トランザクションブロック内にある必要があります。
BEGIN;
CREATE TABLE [IF NOT EXISTS] [schema_name.]table_name (
{
column_name column_type [column_constraints, [...]]
| table_constraints
[,...]
}
);
CALL set_table_property('[schema_name.]<table_name>', '<property>', '<value>');
COMMENT ON COLUMN <[schema_name.]tablename.column> IS '<value>';
COMMENT ON TABLE <[schema_name.]tablename> IS '<value>';
COMMIT;
テーブルプロパティ
プロパティは、その機能に基づいて 3 つのグループに分類されます。変更不可とマークされたプロパティは、テーブル作成後に変更できません。テーブルを再作成する必要があります。
データ編成 (作成後は変更不可)
| プロパティ | 説明 | 列指向 | 行指向 | 行列ハイブリッド | デフォルト |
|---|---|---|---|---|---|
orientation |
ストレージフォーマットを設定します。詳細については、「ストレージモード」をご参照ください。 | column |
row |
row,column |
column |
distribution_key |
データシャーディングポリシーを設定します。詳細については、「分散キー」をご参照ください。 | デフォルトではプライマリキーです。最高のパフォーマンスを得るには、プライマリキーから 1 つの列を選択します。 | デフォルトではプライマリキーです。 | デフォルトではプライマリキーです。 | プライマリキー |
clustering_key |
ファイル内でデータを物理的にソートし、範囲クエリを高速化します。詳細については、「クラスタリングキー」をご参照ください。 | デフォルトでは空です。最大 1 つの列を使用し、昇順のみがサポートされます。 | デフォルトではプライマリキーです。 | デフォルトでは空です。 | — |
event_time_column |
時間によってデータをファイルセグメントに分割し、高速な時間範囲フィルタリングを可能にします。詳細については、「イベント時間列」をご参照ください。 | デフォルトでは、NULL でない最初のタイムスタンプフィールドです。 | サポートされていません。 | デフォルトでは、NULL でない最初のタイムスタンプフィールドです。 | NULL でない最初のタイムスタンプ |
table_group |
データ分散のためのシャード数を制御します。詳細については、「テーブルグループとシャード数」をご参照ください。 | デフォルトのテーブルグループ。 | デフォルトのテーブルグループ。 | デフォルトのテーブルグループ。 | デフォルトのテーブルグループ |
orientation、distribution_key、clustering_key、および event_time_column はテーブル作成後に変更できません。テーブルを作成する前に、これらを慎重に計画してください。table_group も、テーブルの再作成や再シャーディングなしでは変更できません。
インデックスアクセラレーション (作成後に変更可能)
| プロパティ | 説明 | 列指向 | 行指向 | 行列ハイブリッド |
|---|---|---|---|---|
bitmap_columns |
低カーディナリティ列での高速な等価フィルタリングのためにビットマップインデックスを構築します。詳細については、「ビットマップインデックス」をご参照ください。等価比較で使用する列に設定し、10 列以上設定することは避けてください。 | サポートされています | サポートされていません | サポートされています |
dictionary_encoding_columns |
文字列比較を数値比較に変換する辞書マップを構築し、GROUP BY および FILTER 操作を高速化します。列指向テーブルのすべての TEXT 列はデフォルトで有効になっています。V0.9 以降では、Hologres はデータ特性に基づいて辞書エンコーディングを適用するかどうかを自動的に決定します。 | サポートされています | サポートされていません | サポートされています |
bitmap_columns と dictionary_encoding_columns は、テーブル作成後に ALTER TABLE を介して変更できます。
`dictionary_encoding_columns` 構文:
CALL set_table_property('table_name', 'dictionary_encoding_columns', '[columnName{:[on|off|auto]}[,...]]');
データライフサイクル
| プロパティ | 説明 | 列指向 | 行指向 | 行列ハイブリッド |
|---|---|---|---|---|
time_to_live_in_seconds |
テーブルデータの Time to Live (TTL) を秒単位で設定します。TTL は更新時間ではなく、書き込み時間から開始されます。V1.3.24 以降では、許可される最小値は 86,400 (1 日) です。 | サポートされています | 推奨されません — デフォルト値を使用してください | 推奨されません |
storage_mode |
データがホットストレージまたはコールドストレージに保存されるかを指定します。V1.3 以降でサポートされています。詳細については、「階層化データストレージ」をご参照ください。 | 必要に応じて使用 | 必要に応じて使用 | — |
`time_to_live_in_seconds` の注意点:
-
TTL は正確な時間に強制されるわけではありません。TTL の有効期限が切れた後、データは正確な瞬間ではなく、一定のウィンドウ内で削除されます。
-
データのみが削除され、テーブル自体は残ります。
-
TTL は、削除後にプライマリキーの重複やクエリ結果の不整合を引き起こす可能性があります。
-
本番データのライフサイクル管理には、代わりにパーティションテーブルを使用してください。詳細については、「CREATE PARTITION TABLE」をご参照ください。
-
Hologres V4.2 以降、プライマリキーを持つテーブルの場合、TTL 設定は GUC パラメーター
hg_time_to_live_in_days_min_valueによって制約されます。このパラメーターは日数単位で測定され、デフォルト値は 36500 (100 年) で、スーパーユーザーのみが変更できます。CREATE TABLE 、ALTER TABLE 、SET_TABLE_PROPERTY 、またはREBUILD を介してプライマリキーテーブルの TTL を設定する場合、システムは値が最小要件 (hg_time_to_live_in_days_min_valueに対応する日数以上) を満たしていることを確認します。プライマリキーのないテーブルは、この制約の影響を受けません。
設定されていない場合、デフォルトの TTL は 100 年 (事実上有効期限なし) です。
`time_to_live_in_seconds` 構文:
CALL set_table_property('table_name', 'time_to_live_in_seconds', '<non_negative_literal>');
`storage_mode` 構文:
-- テーブル作成時にストレージモードを設定:
CREATE TABLE <table_name> (...) WITH (storage_mode = 'hot');
CREATE TABLE <table_name> (...) WITH (storage_mode = 'cold');
-- テーブル作成後にストレージモードを設定:
CALL set_table_property('table_name', 'storage_mode', 'hot');
CALL set_table_property('table_name', 'storage_mode', 'cold');
例
例:大規模時系列データのためのパーティションテーブル
データ量が増加するにつれて、単一のフラットテーブルの維持コストは高くなります。既存データのパージには全行のスキャンが必要であり、時間ベースのクエリは全表スキャンを実行します。パーティションテーブルは、日ごとにデータを物理的に分離し、クリーンアップのための即時パーティションドロップと、クエリ中の自動パーティションプルーニングを可能にします。
この例では、「クイックスタート」セクションの dwd_trade_orders テーブルをパーティション構造にアップグレードします。フィールド定義とインデックス設定は継承されますが、プライマリキーにはパーティションキー dt を含める必要があります。
BEGIN;
-- パーティション化された親テーブルを作成します。
-- プライマリキーには、ビジネスキー (order_id) とパーティションキー (dt) の両方が含まれます。
CREATE TABLE IF NOT EXISTS public.dwd_trade_orders_partitioned (
order_id BIGINT NOT NULL,
shop_id INT NOT NULL,
user_id TEXT NOT NULL,
order_amount NUMERIC(12, 2) DEFAULT 0.00,
payment NUMERIC(12, 2) DEFAULT 0.00,
payment_type INT DEFAULT 0,
is_delivered BOOLEAN DEFAULT false,
dt TEXT NOT NULL,
order_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (order_id, dt)
)
PARTITION BY LIST (dt)
WITH (
orientation = 'column',
distribution_key = 'order_id',
event_time_column = 'order_time',
clustering_key = 'order_time:asc'
);
COMMIT;
-- 特定の日付の物理ストレージを提供するために子テーブルを作成します。
CREATE TABLE IF NOT EXISTS public.dwd_trade_orders_20231101
PARTITION OF public.dwd_trade_orders_partitioned FOR VALUES IN ('20231101');
-- データを挿入します。アプリケーションロジックはフラットテーブルと同じです。
-- データは自動的に正しい子テーブルにルーティングされます。
INSERT INTO public.dwd_trade_orders_partitioned
(order_id, shop_id, user_id, order_amount, payment, payment_type, is_delivered, dt, order_time)
VALUES
(50001, 101, 'U678', 299.00, 280.00, 1, true, '20231101', '2023-11-01 10:00:01+08'),
(50002, 102, 'U992', 59.00, 59.00, 2, false, '20231101', '2023-11-01 10:05:12+08'),
(50003, 101, 'U441', 150.00, 145.00, 1, true, '20231101', '2023-11-01 10:10:45+08'),
(50004, 105, 'U219', 888.00, 888.00, 3, true, '20231101', '2023-11-01 10:20:11+08'),
(50005, 102, 'U883', 35.00, 30.00, 1, false, '20231101', '2023-11-01 10:32:00+08'),
(50006, 110, 'U007', 120.50, 120.50, 2, true, '20231101', '2023-11-01 10:45:33+08'),
(50007, 101, 'U321', 210.00, 210.00, 1, true, '20231101', '2023-11-01 11:02:19+08'),
(50008, 108, 'U556', 45.00, 45.00, 2, false, '20231101', '2023-11-01 11:15:04+08'),
(50009, 101, 'U112', 300.00, 290.00, 3, true, '20231101', '2023-11-01 11:25:55+08'),
(50010, 105, 'U449', 99.90, 99.90, 1, true, '20231101', '2023-11-01 11:40:22+08');
-- パーティションフィルターを使用してクエリを実行します。Hologres は一致する子テーブルのみをスキャンします。
SELECT COUNT(*) FROM public.dwd_trade_orders_partitioned WHERE dt = '20231101';
-- 子テーブルをドロップして、数秒でスペースを解放します (DELETE よりもはるかに高速です)。
-- DROP TABLE public.dwd_trade_orders_20231101;
例:大規模データセットのリアルタイム分析 (ファクトテーブル)
シナリオ: 大量のデータを持つリアルタイムダッシュボードのサマリーで、中核的な要件は高速な集約です。例えば、商品総売上高 (GMV) や注文数の計算などです。
列指向ストレージはここで優れています。高い圧縮率が I/O を削減し、列スキャンは集約に必要な列のみを読み取ります。
BEGIN;
CREATE TABLE IF NOT EXISTS public.dwd_order_summary (
order_id BIGINT PRIMARY KEY,
category_id INT NOT NULL,
gmv NUMERIC(15, 2),
order_time TIMESTAMPTZ NOT NULL
) WITH (
orientation = 'column', -- 大規模集約に最適。高い圧縮率、効率的な列スキャン
distribution_key = 'order_id', -- 均等な分散。他の注文テーブルとのローカル結合を可能にする
event_time_column = 'order_time', -- 時間範囲フィルターのファイルレベルのセグメントクリッピングを有効化
clustering_key = 'order_time:asc' -- 「過去 1 時間」や「特定の日」のクエリのディスク I/O を削減
);
COMMENT ON TABLE public.dwd_order_summary IS '注文サマリー詳細のファクトテーブル。';
COMMENT ON COLUMN public.dwd_order_summary.order_id IS '一意の注文 ID。';
COMMENT ON COLUMN public.dwd_order_summary.category_id IS 'カテゴリ ID。';
COMMENT ON COLUMN public.dwd_order_summary.gmv IS '商品総売上高。';
COMMENT ON COLUMN public.dwd_order_summary.order_time IS '注文が行われた時間。';
COMMIT;
例:高同時実行ポイントクエリ (ディメンションテーブル)
シナリオ: 高い秒間クエリ数 (QPS) の下で、user_id によってユーザープロファイルをミリ秒単位で取得します。
行指向ストレージは、プライマリキーベースのルックアップに最適化されています。すべての行データは隣接して保存されるため、関連のない列をスキャンすることなく、ポイントクエリが非常に高速になります。
BEGIN;
CREATE TABLE IF NOT EXISTS public.dim_user_persona (
user_id TEXT PRIMARY KEY,
user_level INT,
persona_jsonb JSONB
) WITH (
orientation = 'row'
-- 行指向テーブルの場合、プライマリキーは自動的に分散キー
-- およびクラスタリングキーとして使用されます。追加の設定は不要です。
);
COMMENT ON TABLE public.dim_user_persona IS 'ユーザープロファイルのディメンションテーブル。';
COMMENT ON COLUMN public.dim_user_persona.user_id IS '一意のユーザー ID。';
COMMENT ON COLUMN public.dim_user_persona.user_level IS 'ユーザーレベル。';
COMMENT ON COLUMN public.dim_user_persona.persona_jsonb IS 'JSON 形式のユーザープロファイル特徴。';
COMMIT;
例:ハイブリッドワークロード (行列ハイブリッドストレージ)
シナリオ: 物流状況の要約 (分析) と、order_id による注文詳細の取得 (ポイントクエリ) の両方を必要とする物流およびアフターサービスシステム。
行列ハイブリッドストレージは、行指向ストレージのミリ秒レベルのポイントクエリパフォーマンスと、列指向ストレージの効率的な集約を組み合わせたものです。
BEGIN;
CREATE TABLE IF NOT EXISTS public.ads_shipping_info (
order_id BIGINT PRIMARY KEY,
shipping_status INT,
receiver_address TEXT,
update_time TIMESTAMPTZ
) WITH (
orientation = 'row,column', -- ポイントクエリと集約の両方をサポート
distribution_key = 'order_id', -- シャード間でのデータ分散を制御
bitmap_columns = 'shipping_status' -- 低カーディナリティ列での「status = X」フィルタークエリを高速化
);
COMMENT ON TABLE public.ads_shipping_info IS '物流状況クエリ用のアプリケーションテーブル。';
COMMENT ON COLUMN public.ads_shipping_info.order_id IS '注文 ID。';
COMMENT ON COLUMN public.ads_shipping_info.shipping_status IS '物流状況 (1: 発送待ち, 2: 輸送中, 3: 配達済み)。';
COMMENT ON COLUMN public.ads_shipping_info.receiver_address IS '配送先住所。';
COMMIT;
制限事項
Hologres は、テーブルごとに最大 6,400 列をサポートします。
プライマリキーの制限
-
複合プライマリキー: 複数のフィールドでプライマリキーを構成できます。すべてのフィールドは
NOT NULLでなければならず、単一の文で宣言する必要があります。BEGIN; CREATE TABLE public.test ( id TEXT NOT NULL, ds TEXT NOT NULL, PRIMARY KEY (id, ds) ); CALL SET_TABLE_PROPERTY('public.test', 'orientation', 'column'); COMMIT; -
サポートされていない型: FLOAT、DOUBLE、NUMERIC、ARRAY、JSON、DATE、およびその他の複雑な型は、プライマリキー列として使用できません。
-
変更不可: プライマリキーはテーブル作成後に変更できません。異なるプライマリキーが必要な場合は、テーブルを再作成してください。
-
ストレージ要件: 行指向および行列ハイブリッドテーブルにはプライマリキーが必要です。列指向テーブルではプライマリキーはオプションです。
制約のサポート
| 制約 | 列レベル | テーブルレベル |
|---|---|---|
primary key |
サポートされています | サポートされています |
not null |
サポートされています | — |
null |
サポートされています | — |
unique |
サポートされていません | サポートされていません |
check |
サポートされていません | サポートされていません |
default |
サポートされています | サポートされていません |
命名およびエスケープルール
-
列名を
hg_で始めることはできません。 -
スキーマ名を
holo_、hg_、またはpg_で始めることはできません。 -
テーブル名は 127 バイトを超えることはできません。
-
名前が SQL キーワード、予約語、システムフィールド (例:
ctid)、大文字と小文字を区別する識別子、特殊文字を含む、または数字で始まる場合は、名前を二重引用符 ("") で囲んでください。
Hologres V2.0 以降のエスケープされた列名の構文:
-- 単一のエスケープされた列
BEGIN;
CREATE TABLE tbl (c1 INT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"c1":asc');
COMMIT;
-- 複数の列、大文字を含む (V2.1 以降)
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL) WITH (clustering_key = '"C1",c2');
COMMIT;
-- 複数の列、大文字を含む (V2.0 以降)
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"C1",c2');
COMMIT;
Hologres V2.0 より前のバージョンのエスケープされた列名の構文:
BEGIN;
CREATE TABLE tbl (c1 INT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"c1:asc"');
COMMIT;
-- 複数の列、大文字を含む
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"C1,c2"');
COMMIT;
必要に応じて Hologres V2.0 で古いパーサー構文に切り替えるには:
-- セッションレベルで古い構文を有効にします。
SET hg_disable_parse_holo_property = on;
-- データベースレベルで古い構文を有効にします。
ALTER DATABASE <db_name> SET hg_disable_parse_holo_property = on;
IF NOT EXISTS の動作
| 条件 | IF NOT EXISTS が指定されている場合 |
IF NOT EXISTS が指定されていない場合 |
|---|---|---|
| 同じ名前のテーブルが存在する | NOTICE を返し、作成をスキップし、操作は成功します | ERROR を返します |
| 同じ名前のテーブルが存在しない | 操作は成功します | 操作は成功します |
変更の制限
テーブルが作成された後、以下は変更できません。
-
データ型 (Hologres V3.0 より前)
-
列の順序
-
NULL 値許容制約 (
NOT NULL↔ NULL 値許容) -
ストレージレイアウトプロパティ:
orientation、distribution_key、clustering_key、event_time_column
以下はテーブル作成後に変更できます。
-
bitmap_columnsおよびdictionary_encoding_columns— ALTER TABLE を介して -
データ型:V3.0 以降の一部の型、V3.1 以降の REBUILD を介したすべての型 — 詳細については、「データ型の変更」および「REBUILD」をご参照ください
次のステップ
-
CREATE PARTITION TABLE — パーティションテーブルを使用して大規模なデータライフサイクルを管理する
-
ALTER TABLE — テーブル作成後に変更可能なプロパティを変更する
-
分散キー — 適切な分散キーの選択方法を学ぶ
-
クラスタリングキー — クラスタリングキーがクエリパフォーマンスを向上させる仕組みを理解する
-
ストレージモード — 列指向、行指向、行列ハイブリッドストレージを詳細に比較する