Use CREATE TABLE para definir o layout de armazenamento de uma tabela no Hologres. Configurar corretamente o modo de armazenamento, a chave de distribuição e os índices durante a criação é fundamental, pois a maioria dessas propriedades não pode ser alterada posteriormente.
Pré-requisitos
Antes de começar, verifique se você tem:
Conexão com o banco de dados de destino — o HoloWeb é a ferramenta recomendada para executar consultas
Início rápido
Este exemplo cria uma tabela de detalhes de transações com a sintaxe CREATE TABLE WITH (disponível no Hologres V2.1 e posterior). O exemplo adota uma convenção de nomenclatura hierárquica, define vários campos e inclui comentários de metadados.
BEGIN;
-- Create a transaction details fact table.
-- Use the public schema and follow the hierarchical naming convention (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: Unpaid, 1: Alipay, 2: WeChat Pay, 3: Credit Card
is_delivered BOOLEAN DEFAULT false,
dt TEXT NOT NULL, -- Data timestamp, in YYYYMMDD format
order_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (order_id)
)
WITH (
orientation = 'column', -- Column-oriented: best for OLAP aggregation on large datasets
distribution_key = 'order_id', -- Shard data by order_id for even distribution
clustering_key = 'order_time:asc', -- Sort data by time within files to accelerate range queries
event_time_column = 'order_time', -- Enable file-level clipping for time range filters
bitmap_columns = 'shop_id,payment_type,is_delivered', -- Accelerate equality filters on low-cardinality columns
dictionary_encoding_columns = 'user_id:auto' -- Accelerate GROUP BY and FILTER on string columns
);
-- Add metadata comments.
COMMENT ON TABLE public.dwd_trade_orders IS 'Base fact table for transaction order details.';
COMMENT ON COLUMN public.dwd_trade_orders.order_id IS 'The unique identifier of the order.';
COMMENT ON COLUMN public.dwd_trade_orders.shop_id IS 'The unique ID of the shop.';
COMMENT ON COLUMN public.dwd_trade_orders.user_id IS 'The ID of the buyer.';
COMMENT ON COLUMN public.dwd_trade_orders.dt IS 'The data timestamp, in YYYYMMDD format.';
COMMENT ON COLUMN public.dwd_trade_orders.order_time IS 'The precise timestamp when the order was created.';
COMMIT;
Visualize o esquema da tabela
Execute a consulta a seguir para obter a instrução DDL (Data Definition Language) da tabela:
SELECT hg_dump_script('public.dwd_trade_orders');
Insira dados
O Hologres é compatível com a sintaxe padrão DML (Data Manipulation Language). A instrução abaixo insere 10 linhas de dados de exemplo:
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');
Consulte dados
-- Calculate the total transaction amount per shop, sorted in descending order.
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;
Saída esperada:
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
Sintaxe
Sintaxe do CREATE TABLE
O Hologres oferece suporte a duas sintaxes para definir propriedades e comentários de tabela:
Sintaxe padrão (recomendada para Hologres V2.1 e posterior)
Use a palavra-chave WITH para definir propriedades diretamente na instrução. Esta sintaxe é mais compacta e oferece melhor desempenho.
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;
Sintaxe compatível (suportada em todas as versões)
Use CALL set_table_property para configurar propriedades e COMMENT para adicionar comentários. Todas as instruções devem estar no mesmo bloco de transação BEGIN...COMMIT do CREATE TABLE.
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;
Propriedades da tabela
As propriedades dividem-se em três grupos conforme sua função. As propriedades marcadas como não modificáveis não podem ser alteradas após a criação da tabela — nesse caso, recrie a tabela.
Organização de dados (não modificável após a criação)
|
Propriedade |
Descrição |
Orientada a colunas |
Orientada a linhas |
Híbrida (linha-coluna) |
Padrão |
|
|
Define o formato de armazenamento. Consulte Modos de armazenamento. |
|
|
|
|
|
|
Define a política de fragmentação de dados. Consulte Chave de distribuição. |
Chave primária por padrão; escolha uma coluna da chave primária para obter o melhor desempenho. |
Chave primária por padrão. |
Chave primária por padrão. |
Chave primária |
|
|
Ordena fisicamente os dados nos arquivos para acelerar consultas de intervalo. Consulte Chave de clusterização. |
Vazio por padrão. Use no máximo uma coluna; apenas a ordem crescente é suportada. |
Chave primária por padrão. |
Vazio por padrão. |
— |
|
|
Segmenta os dados em arquivos por tempo, permitindo filtragem rápida por intervalo temporal. Consulte Coluna de tempo de evento. |
Primeiro campo de timestamp não nulo por padrão. |
Não suportado. |
Primeiro campo de timestamp não nulo por padrão. |
Primeiro timestamp não nulo |
|
|
Controla a contagem de shards para distribuição de dados. Consulte Grupos de tabelas e contagem de shards. |
Grupo de tabelas padrão. |
Grupo de tabelas padrão. |
Grupo de tabelas padrão. |
Grupo de tabelas padrão |
As propriedades orientation, distribution_key, clustering_key e event_time_column não podem ser modificadas após a criação da tabela. Planeje-as cuidadosamente antes de criar a tabela. A propriedade table_group também não pode ser alterada sem recriar a tabela ou executar um novo particionamento (resharding).
Aceleração por índice (modificável após a criação)
|
Propriedade |
Descrição |
Orientada a colunas |
Orientada a linhas |
Híbrida (linha-coluna) |
|
|
Cria um índice bitmap para filtragem rápida por igualdade em colunas de baixa cardinalidade. Consulte Índice bitmap. Use em colunas de comparações de igualdade; evite configurar mais de 10 colunas. |
Suportado |
Não suportado |
Suportado |
|
|
Cria um mapeamento de dicionário que converte comparações de strings em comparações numéricas, acelerando operações de GROUP BY e FILTER. Todas as colunas TEXT em tabelas orientadas a colunas são habilitadas por padrão. A partir da versão V0.9, o Hologres determina automaticamente se deve aplicar a codificação de dicionário com base nas características dos dados. |
Suportado |
Não suportado |
Suportado |
Tanto bitmap_columns quanto dictionary_encoding_columns podem ser modificados após a criação da tabela por meio do comando ALTER TABLE.
Sintaxe de dictionary_encoding_columns:
CALL set_table_property('table_name', 'dictionary_encoding_columns', '[columnName{:[on|off|auto]}[,...]]');
Ciclo de vida dos dados
|
Propriedade |
Descrição |
Orientada a colunas |
Orientada a linhas |
Híbrida (linha-coluna) |
|
|
Define o TTL (Time to Live) dos dados da tabela em segundos. O TTL conta a partir do momento da escrita, não da atualização. Nas versões V1.3.24 e posteriores, o valor mínimo permitido é 86.400 (um dia). |
Suportado |
Não recomendado — use o valor padrão |
Não recomendado |
|
|
Especifica se os dados ficam em armazenamento quente ou frio. Suportado na versão V1.3 e posteriores. Consulte Armazenamento de dados em camadas. |
Use conforme necessário |
Use conforme necessário |
— |
Observações sobre time_to_live_in_seconds:
O TTL não é aplicado em um horário exato. Após a expiração, os dados são excluídos dentro de uma janela de tempo, e não em um momento preciso.
Apenas os dados são excluídos; a tabela permanece intacta.
O uso de TTL pode causar chaves primárias duplicadas ou resultados de consulta inconsistentes após a exclusão.
Para gerenciar o ciclo de vida de dados em produção, prefira tabelas particionadas. Consulte CREATE PARTITION TABLE.
A partir do Hologres V4.2, para tabelas com chave primária, a configuração de TTL é restringida pelo parâmetro GUC
hg_time_to_live_in_days_min_value. Este parâmetro é medido em dias, tem valor padrão de 36500 (100 anos) e só pode ser modificado por um Superusuário. Ao definir o TTL de uma tabela com chave primária via CREATE TABLE, ALTER TABLE, SET_TABLE_PROPERTY ou REBUILD, o sistema verifica se o valor atende ao requisito mínimo (deve ser maior ou igual ao número de dias correspondente ahg_time_to_live_in_days_min_value). Tabelas sem chave primária não sofrem essa restrição.
Se não definido, o TTL padrão é de 100 anos (efetivamente sem expiração).
Sintaxe de time_to_live_in_seconds:
CALL set_table_property('table_name', 'time_to_live_in_seconds', '<non_negative_literal>');
Sintaxe de storage_mode:
-- Set storage mode at table creation:
CREATE TABLE <table_name> (...) WITH (storage_mode = 'hot');
CREATE TABLE <table_name> (...) WITH (storage_mode = 'cold');
-- Set storage mode after table creation:
CALL set_table_property('table_name', 'storage_mode', 'hot');
CALL set_table_property('table_name', 'storage_mode', 'cold');
Exemplos
Exemplo: Tabela particionada para dados de séries temporais em grande escala
À medida que o volume de dados cresce, manter uma única tabela plana torna-se custoso — limpar dados históricos exige varrer todas as linhas, e consultas baseadas em tempo realizam varreduras completas na tabela. Uma tabela particionada isola fisicamente os dados por dia, permitindo remover partições instantaneamente para limpeza e aplicar poda automática de partições durante as consultas.
Este exemplo atualiza a tabela dwd_trade_orders da seção Início rápido para uma estrutura particionada. As definições de campos e configurações de índice são herdadas, mas a chave primária deve incluir a chave de partição dt.
BEGIN;
-- Create the partitioned parent table.
-- The primary key includes both the business key (order_id) and the partition key (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 a child table to provide physical storage for a specific date.
CREATE TABLE IF NOT EXISTS public.dwd_trade_orders_20231101
PARTITION OF public.dwd_trade_orders_partitioned FOR VALUES IN ('20231101');
-- Insert data. The application logic is identical to the flat table.
-- Data is automatically routed to the correct child table.
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');
-- Query with a partition filter. Hologres scans only the matching child table.
SELECT COUNT(*) FROM public.dwd_trade_orders_partitioned WHERE dt = '20231101';
-- Drop a child table to reclaim space in seconds (much faster than DELETE).
-- DROP TABLE public.dwd_trade_orders_20231101;
Exemplo: Análises em tempo real para grandes conjuntos de dados (tabela de fatos)
Cenário: Resumos de painéis em tempo real com grandes volumes de dados, cujo requisito principal é a agregação rápida — por exemplo, calcular o Volume Bruto de Mercadorias (GMV) e a contagem de pedidos.
O armazenamento orientado a colunas é ideal para este caso: altas taxas de compressão reduzem a E/S, e as varreduras de colunas leem apenas as colunas necessárias para a agregaçã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', -- Best for large-scale aggregation; high compression, efficient column scans
distribution_key = 'order_id', -- Even distribution; enables local joins with other order tables
event_time_column = 'order_time', -- Enables file-level segment clipping for time range filters
clustering_key = 'order_time:asc' -- Reduces disk I/O for "last hour" or "specific day" queries
);
COMMENT ON TABLE public.dwd_order_summary IS 'Fact table for order summary details.';
COMMENT ON COLUMN public.dwd_order_summary.order_id IS 'The unique order ID.';
COMMENT ON COLUMN public.dwd_order_summary.category_id IS 'The category ID.';
COMMENT ON COLUMN public.dwd_order_summary.gmv IS 'The gross merchandise volume.';
COMMENT ON COLUMN public.dwd_order_summary.order_time IS 'The time when the order was placed.';
COMMIT;
Exemplo: Consultas pontuais de alta concorrência (tabela de dimensões)
Cenário: Recuperar o perfil de um usuário por user_id em milissegundos, sob alta taxa de consultas por segundo (QPS).
O armazenamento orientado a linhas é otimizado para buscas baseadas em chave primária. Todos os dados da linha ficam armazenados de forma contígua, tornando as consultas pontuais extremamente rápidas, sem necessidade de varrer colunas irrelevantes.
BEGIN;
CREATE TABLE IF NOT EXISTS public.dim_user_persona (
user_id TEXT PRIMARY KEY,
user_level INT,
persona_jsonb JSONB
) WITH (
orientation = 'row'
-- For row-oriented tables, the primary key is automatically used as the distribution key
-- and clustering key. No additional settings are required.
);
COMMENT ON TABLE public.dim_user_persona IS 'Dimension table for user profiles.';
COMMENT ON COLUMN public.dim_user_persona.user_id IS 'The unique user ID.';
COMMENT ON COLUMN public.dim_user_persona.user_level IS 'The user level.';
COMMENT ON COLUMN public.dim_user_persona.persona_jsonb IS 'The user profile features in JSON format.';
COMMIT;
Exemplo: Carga de trabalho híbrida (armazenamento híbrido linha-coluna)
Cenário: Sistema de logística e pós-venda que necessita tanto de análises (resumo de status logísticos) quanto de consultas pontuais (recuperação de detalhes de pedidos por order_id).
O armazenamento híbrido linha-coluna combina o desempenho de consultas pontuais em nível de milissegundos do armazenamento orientado a linhas com a eficiência de agregação do armazenamento orientado a colunas.
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', -- Supports both point queries and aggregation
distribution_key = 'order_id', -- Controls data distribution across shards
bitmap_columns = 'shipping_status' -- Accelerates "status = X" filter queries on a low-cardinality column
);
COMMENT ON TABLE public.ads_shipping_info IS 'Application table for logistics status queries.';
COMMENT ON COLUMN public.ads_shipping_info.order_id IS 'The order ID.';
COMMENT ON COLUMN public.ads_shipping_info.shipping_status IS 'Logistics status (1: To be shipped, 2: In transit, 3: Delivered).';
COMMENT ON COLUMN public.ads_shipping_info.receiver_address IS 'The shipping address.';
COMMIT;
Limitações
O Hologres suporta no máximo 6.400 colunas por tabela.
Limites de chave primária
-
Composite primary keys: Vários campos podem formar a chave primária. Todos os campos devem ser
NOT NULLe declarados em uma única instrução.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; Tipos não suportados: FLOAT, DOUBLE, NUMERIC, ARRAY, JSON, DATE e outros tipos complexos não podem ser usados como colunas de chave primária.
Não modificável: A chave primária não pode ser alterada após a criação da tabela. Recrie a tabela caso precise de uma chave primária diferente.
Requisitos de armazenamento: Tabelas orientadas a linhas e híbridas (linha-coluna) devem ter uma chave primária. Para tabelas orientadas a colunas, a chave primária é opcional.
Suporte a restrições
|
Restrição |
Nível de coluna |
Nível de tabela |
|
|
Suportado |
Suportado |
|
|
Suportado |
— |
|
|
Suportado |
— |
|
|
Não suportado |
Não suportado |
|
|
Não suportado |
Não suportado |
|
|
Suportado |
Não suportado |
Regras de nomenclatura e escape
Nomes de colunas não podem começar com
hg_.Nomes de esquemas não podem começar com
holo_,hg_oupg_.Nomes de tabelas não podem exceder 127 bytes.
Coloque nomes entre aspas duplas (
"") quando forem palavras-chave SQL, palavras reservadas, campos do sistema (comoctid), identificadores sensíveis a maiúsculas e minúsculas, nomes com caracteres especiais ou nomes iniciados por dígito.
Sintaxe para nomes de colunas com escape no Hologres V2.0 e posterior:
-- Single escaped column
BEGIN;
CREATE TABLE tbl (c1 INT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"c1":asc');
COMMIT;
-- Multiple columns, including an uppercase one (V2.1 and later)
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL) WITH (clustering_key = '"C1",c2');
COMMIT;
-- Multiple columns, including an uppercase one (V2.0 and later)
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"C1",c2');
COMMIT;
Sintaxe para nomes de colunas com escape em versões anteriores ao Hologres V2.0:
BEGIN;
CREATE TABLE tbl (c1 INT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"c1:asc"');
COMMIT;
-- Multiple columns, including an uppercase one
BEGIN;
CREATE TABLE tbl ("C1" INT NOT NULL, c2 TEXT NOT NULL);
CALL set_table_property('tbl', 'clustering_key', '"C1,c2"');
COMMIT;
Para alternar para a sintaxe antiga do analisador no Hologres V2.0 quando necessário:
-- Enable the old syntax at the session level.
SET hg_disable_parse_holo_property = on;
-- Enable the old syntax at the database level.
ALTER DATABASE <db_name> SET hg_disable_parse_holo_property = on;
Comportamento do IF NOT EXISTS
|
Condição |
** |
** |
|
Existe uma tabela com o mesmo nome |
Retorna um NOTICE, ignora a criação, operação bem-sucedida |
Retorna um ERROR |
|
Não existe tabela com o mesmo nome |
Operação bem-sucedida |
Operação bem-sucedida |
Limites de modificação
Após a criação da tabela, os seguintes itens não podem ser alterados:
Tipos de dados (antes do Hologres V3.0)
Ordem das colunas
Restrição de nulidade (
NOT NULL↔ anulável)Propriedades de layout de armazenamento:
orientation,distribution_key,clustering_key,event_time_column
Os seguintes itens podem ser alterados após a criação da tabela:
bitmap_columnsedictionary_encoding_columns— via ALTER TABLETipos de dados: alguns tipos na versão V3.0 e posterior; todos os tipos via REBUILD na versão V3.1 e posterior — consulte Modificar tipos de dados e REBUILD
Próximos passos
CREATE PARTITION TABLE — gerencie o ciclo de vida dos dados em escala usando tabelas particionadas
ALTER TABLE — modifique propriedades alteráveis após a criação da tabela
Chave de distribuição — aprenda a escolher a chave de distribuição adequada
Chave de clusterização — entenda como as chaves de clusterização melhoram o desempenho das consultas
Modos de armazenamento — compare detalhadamente os armazenamentos orientados a colunas, orientados a linhas e híbridos