Colunas geradas são colunas especiais calculadas a partir de outras colunas. Elas se dividem em colunas geradas armazenadas e colunas geradas virtuais. A partir do Hologres V3.1, o sistema oferece suporte a colunas geradas armazenadas, que são calculadas automaticamente durante a gravação ou atualização de dados e ocupam espaço de armazenamento. Ainda não há suporte para colunas geradas virtuais. Este tópico descreve como usar colunas geradas armazenadas no Hologres.
Cenários
Cálculo automático de campos obrigatórios: elimina a necessidade de processar manualmente a lógica de cálculo.
Consistência de dados: evita inconsistências causadas por erros humanos ou problemas na lógica do código.
Otimização de desempenho de consultas: em cenários de consulta de alta frequência, a leitura de colunas geradas armazenadas equivale à leitura de colunas comuns.
Simplificação da lógica de negócios: reduz a complexidade do SQL em operações fixas e comuns de transformação de dados.
O uso adequado de colunas geradas, conforme as necessidades do seu negócio, melhora significativamente a eficiência do desenvolvimento e garante a confiabilidade dos dados.
Sintaxe
Use a cláusula GENERATED ALWAYS AS para declarar uma coluna gerada e a palavra-chave STORED para especificar uma coluna gerada armazenada.
-
Crie uma tabela com uma coluna gerada.
CREATE TABLE generated_col_t ( [...,] col1 INT, col2 INT GENERATED ALWAYS AS (col1 + 1) STORED ); -
Crie uma tabela particionada lógica que contenha uma coluna gerada e use-a como chave de partição.
CREATE TABLE generated_col_logical_part ( a TEXT, b INT, ts TIMESTAMP NOT NULL, d TIMESTAMP GENERATED ALWAYS AS (date_trunc('day', ts)) STORED NOT NULL ) LOGICAL PARTITION BY LIST(d);
Precauções
-
CREATE TABLE
Na definição de uma coluna gerada, apenas funções ou expressões IMMUTABLE têm suporte. Funções não imutáveis, como CURRENT_DATE e RANDOM, não são aceitas.
A expressão de uma coluna gerada não pode referenciar outra coluna gerada. Também não é possível definir um valor
defaultpara uma coluna gerada.Ao criar uma tabela particionada, você pode definir a chave de partição de uma tabela particionada lógica como uma coluna gerada, mas não é possível definir a chave de partição de uma tabela particionada física como uma coluna gerada. Colunas regulares em tabelas particionadas podem ser configuradas como colunas geradas.
Não há suporte para colunas geradas ao criar uma tabela externa com CREATE FOREIGN TABLE.
Colunas geradas podem atuar como diversos índices do Hologres, incluindo chaves primárias, chaves de distribuição, chaves de segmento, índices clusterizados, índices bitmap e colunas codificadas por dicionário.
-
ALTER TABLE
Não é possível adicionar uma coluna como coluna gerada.
É possível remover uma coluna gerada. No entanto, antes de removê-la, não é permitido excluir as colunas referenciadas por ela.
Não é possível modificar o tipo de dados de uma coluna gerada ou os tipos de dados das colunas que ela referencia. Recomendamos usar o recurso REBUILD para essa finalidade. Para mais informações, consulte REBUILD.
É permitido renomear uma coluna gerada.
-
DML/DQL
Ao inserir ou atualizar dados, omita a coluna gerada da instrução ou especifique seu valor como
default. Não insira diretamente um valor específico em uma coluna gerada.Durante a atualização de dados, se uma coluna gerada ou sua coluna referenciada for uma chave de distribuição, não haverá suporte para atualizar essa coluna.
Para executar atualizações usando um plano fixo, caso a chave primária inclua uma coluna gerada, ela também deverá conter todas as colunas referenciadas por essa coluna gerada.
Ao realizar atualizações parciais de colunas com um plano fixo, se uma coluna gerada referenciar múltiplas colunas regulares, não haverá suporte para atualizar apenas algumas dessas colunas.
Todas as demais operações em tabelas com colunas geradas têm suporte, incluindo leituras e gravações executadas pelo mecanismo HQE, operações de leitura e escrita via planos fixos e comandos como Copy.
-
Outras operações
O comando
CREATE TABLE LIKEaceita tabelas que contêm colunas geradas. Ative o parâmetrohg_experimental_enable_create_table_like_propertiespara preservar as propriedades das colunas geradas.Não há suporte para tabelas de origem com colunas geradas ao usar CREATE TABLE AS.
Para modificar parâmetros de uma tabela com colunas geradas, use a sintaxe REBUILD (incluindo a migração do grupo de tabelas). Para mais informações, consulte REBUILD. Não há suporte para migrar o grupo de tabelas usando a sintaxe HG_MOVE_TABLE_TO_TABLE_GROUP.
Para executar uma operação
INSERT OVERWRITEem uma tabela com colunas geradas, use a sintaxe nativaINSERT OVERWRITEdisponível no Hologres V3.1 e versões posteriores. A sintaxe legadahg_insert_overwritenão tem suporte. Para mais informações, consulte INSERT OVERWRITE.
Exemplos
-
Crie uma tabela com uma coluna gerada.
CREATE TABLE generated_col_t ( id INT PRIMARY KEY, col1 INT, col2 INT GENERATED ALWAYS AS (col1 + 1) STORED ); -
Importe dados.
-
Importe dados para todas as colunas não geradas. Exemplo:
INSERT INTO generated_col_t VALUES (1, 1); INSERT INTO generated_col_t(id, col1) VALUES (2, 2);A consulta
SELECT * FROM generated_col_t;retorna o seguinte resultado:id col1 col2 1 1 2 2 2 3 -
Use a palavra-chave
defaultpara a coluna gerada durante a importação de dados. Por exemplo:INSERT INTO generated_col_t VALUES (3, 3, default); INSERT INTO generated_col_t(id, col1, col2) VALUES (4, 4, default);A consulta
SELECT * FROM generated_col_t;retorna o seguinte resultado:id col1 col2 4 4 5 2 2 3 3 3 4 1 1 2 -
Sem suporte: importar dados diretamente para colunas geradas. Exemplo:
INSERT INTO generated_col_t VALUES (5, 5, 6); INSERT INTO generated_col_t(id, col1, col2) VALUES (6, 6, 7);O sistema retorna o seguinte resultado.
ERROR: cannot insert into column "col2" Detail: Column "col2" is a generated column.
-
-
Atualize dados.
-
Atualize colunas não geradas. Exemplo:
UPDATE generated_col_t SET col1 = 2 WHERE id = 1;A consulta
SELECT * FROM generated_col_t;retorna o seguinte resultado:id col1 col2 2 2 3 3 3 4 4 4 5 1 2 3 -- This row has been changed -
Use a palavra-chave
defaultpara a coluna gerada durante uma atualização. Por exemplo:UPDATE generated_col_t SET col1 = 3, col2 = default WHERE id = 2;A consulta
SELECT * FROM generated_col_t;retorna o seguinte resultado:id col1 col2 3 3 4 2 3 4 -- This row has been changed 4 4 5 1 2 3 -
Sem suporte: atualizar diretamente colunas geradas. Exemplo:
UPDATE generated_col_t SET col2 = 4 WHERE id = 3;O sistema retorna o seguinte resultado.
ERROR: column "col2" can only be updated to DEFAULT Detail: Column "col2" is a generated column.
-
Use a seguinte consulta SQL para verificar se uma função é IMMUTABLE para tipos de parâmetros específicos. Por exemplo, a função TO_CHAR é IMMUTABLE apenas quando sua entrada é do tipo TIMESTAMP WITH TIME ZONE. Portanto, ao usar essa função em uma coluna gerada, garanta que o tipo do parâmetro corresponda.
SELECT n.nspname AS "Schema",
p.proname AS "Name",
pg_catalog.pg_get_function_result(p.oid) AS "Result data type",
pg_catalog.pg_get_function_arguments(p.oid) AS "Argument data types",
CASE p.prokind
WHEN 'a' THEN 'agg'
WHEN 'w' THEN 'window'
WHEN 'p' THEN 'proc'
ELSE 'func'
END AS "Type",
CASE
WHEN p.provolatile = 'i' THEN 'immutable'
WHEN p.provolatile = 's' THEN 'stable'
WHEN p.provolatile = 'v' THEN 'volatile'
END AS "Volatility",
CASE
WHEN p.proparallel = 'r' THEN 'restricted'
WHEN p.proparallel = 's' THEN 'safe'
WHEN p.proparallel = 'u' THEN 'unsafe'
END AS "Parallel",
pg_catalog.pg_get_userbyid(p.proowner) AS "Owner",
CASE WHEN prosecdef THEN 'definer' ELSE 'invoker' END AS "Security",
pg_catalog.array_to_string(p.proacl, E'\n') AS "Access privileges",
l.lanname AS "Language",
p.prosrc AS "Source code",
pg_catalog.obj_description(p.oid, 'pg_proc') AS "Description"
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
-- Target function
WHERE p.proname OPERATOR(pg_catalog.~) '^(TO_CHAR)$' COLLATE pg_catalog.default
AND pg_catalog.pg_function_is_visible(p.oid)
ORDER BY 1, 2, 4;