Como atualizar dados de tabela particionada usando DML
Nesta página, você encontra uma visão geral do suporte à linguagem de manipulação de dados (DML) para tabelas particionadas.
Para saber mais sobre a DML, consulte estes tópicos:
- Introdução à DML
- Sintaxe da DML
- Como atualizar dados de tabela usando a linguagem de manipulação de dados
Tabelas usadas nos exemplos
As seguintes definições de esquema JSON representam as tabelas usadas nos exemplos desta página.
mytable
: uma tabela particionada por tempo de ingestão
[ {"name": "field1", "type": "INTEGER"}, {"name": "field2", "type": "STRING"} ]
mytable2
: uma tabela padrão (não particionada)
[ {"name": "id", "type": "INTEGER"}, {"name": "ts", "type": "TIMESTAMP"} ]
mycolumntable
: uma tabela particionada por meio da coluna ts
TIMESTAMP
[ {"name": "field1", "type": "INTEGER"}, {"name": "field2", "type": "STRING"} {"name": "field3", "type": "BOOLEAN"} {"name": "ts", "type": "TIMESTAMP"} ]
Nos exemplos em que COLUMN_ID aparece, substitua-o pelo nome da coluna em que você quer operar.
Como inserir dados
Use uma instrução DML INSERT
para adicionar linhas a uma tabela particionada.
Como inserir dados em tabelas particionadas por tempo de ingestão
Quando você usa uma instrução DML para adicionar linhas a uma tabela particionada por tempo de ingestão, é possível especificar a partição à qual as linhas devem ser adicionadas. Faça referência à partição usando a pseudocoluna _PARTITIONTIME
.
Por exemplo, a instrução INSERT
a seguir adiciona uma linha à partição de 1º de maio de 2017 de mytable
- “2017-05-01”
.
INSERT INTO project_id.dataset.mytable (_PARTITIONTIME, field1, field2) SELECT TIMESTAMP("2017-05-01"), 1, "one"
Somente os carimbos de data/hora que correspondem aos limites de data exatos podem ser usados. Por exemplo, a seguinte instrução DML retorna um erro:
INSERT INTO project_id.dataset.mytable (_PARTITIONTIME, field1, field2) SELECT TIMESTAMP("2017-05-01 21:30:00"), 1, "one"
Como inserir dados em tabelas particionadas
O processo para inserir dados em uma tabela particionada usando DML é igual ao usado para inserir dados em uma tabela não particionada.
Por exemplo, a instrução INSERT
a seguir adiciona linhas à tabela particionada mycolumntable
selecionando dados de mytable2
(uma tabela não particionada).
INSERT INTO project_id.dataset.mycolumntable (ts, field1) SELECT ts, id FROM project_id.dataset.mytable2
Excluir dados
Use uma instrução DML DELETE
para excluir linhas de uma tabela particionada.
Como excluir dados em tabelas particionadas por tempo de ingestão
A seguinte instrução DELETE
exclui todas as linhas da partição de 1º de junho de 2017 ("2017-06-01"
) de mytable
em que field1
é igual a 21
. Faça referência à partição usando a pseudocoluna _PARTITIONTIME
.
DELETE project_id.dataset.mytable WHERE field1 = 21 AND _PARTITIONTIME = "2017-06-01"
Como excluir dados em tabelas particionadas
O processo usado para excluir dados em uma tabela particionada usando DML é igual ao usado para excluir dados de uma tabela não particionada.
Por exemplo, a instrução DELETE
a seguir exclui todas as linhas da partição de 1º de junho de 2017 ("2017-06-01"
) de mycolumntable
, em que field1
é igual a 21
.
DELETE project_id.dataset.mycolumntable WHERE field1 = 21 AND DATE(ts) = "2017-06-01"
Como usar a exclusão DML DELETE para excluir partições
Se uma instrução DELETE
qualificada cobrir todas as linhas em uma partição,
o BigQuery removerá a partição inteira. Essa remoção é feita sem verificar bytes ou consumir slots. O exemplo a seguir de uma instrução DELETE
abrange toda a partição de um filtro na pseudocoluna _PARTITIONDATE
:
DELETE mydataset.mytable WHERE _PARTITIONDATE IN ('2076-10-07', '2076-03-06');
Desqualificações comuns
Consultas com as características a seguir podem não se beneficiar da otimização:
- Cobertura parcial da partição
- Referências a colunas sem particionamento
- Dados ingeridos recentemente usando a API Storage Write do BigQuery ou a API de streaming legada
- Filtros com subconsultas ou predicados não aceitos
A qualificação para otimização pode variar de acordo com o tipo de particionamento, os metadados de armazenamento subjacentes e os predicados de filtro. Como prática recomendada, execute uma simulação para verificar se a consulta resulta em 0 bytes processados.
Transação com várias instruções
Essa otimização funciona em uma transação de várias instruções. O exemplo de consulta a seguir substitui uma partição por dados de outra tabela em uma única transação, sem verificar a partição em busca da instrução DELETE
.
DECLARE REPLACE_DAY DATE; BEGIN TRANSACTION; -- find the partition which we want to replace SET REPLACE_DAY = (SELECT MAX(d) FROM mydataset.mytable_staging); -- delete the entire partition from mytable DELETE FROM mydataset.mytable WHERE part_col = REPLACE_DAY; -- insert the new data into the same partition in mytable INSERT INTO mydataset.mytable SELECT * FROM mydataset.mytable_staging WHERE part_col = REPLACE_DAY; COMMIT TRANSACTION;
Como atualizar dados
Use uma instrução UPDATE
para atualizar linhas em uma tabela particionada.
Como atualizar dados em tabelas particionadas por tempo de ingestão
A instrução UPDATE
a seguir move linhas de uma partição para outra.
As linhas na partição de 1º de maio de 2017 (“2017-05-01”
) de mytable
em que field1
é igual a 21
são movidas para a partição de 1º de junho de 2017 (“2017-06-01”
).
UPDATE project_id.dataset.mytable SET _PARTITIONTIME = "2017-06-01" WHERE _PARTITIONTIME = "2017-05-01" AND field1 = 21
Como atualizar dados em tabelas particionadas
O processo de atualizar dados em uma tabela particionada usando DML é o igual ao usado para atualizar dados de uma tabela não particionada. A instrução UPDATE
a seguir move linhas de uma partição para outra. As linhas na partição de 1º de maio de 2017
(“2017-05-01”
) de mytable
, em que field1
é igual a 21
, são
movidas para a partição de 1º de junho de 2017 (“2017-06-01”
).
UPDATE project_id.dataset.mycolumntable SET ts = "2017-06-01" WHERE DATE(ts) = "2017-05-01" AND field1 = 21
DML em tabelas particionadas por hora, mês e ano
É possível usar instruções DML para modificar uma tabela particionada por hora, mês ou ano. Forneça o intervalo de hora, mês ou ano das datas ou carimbos de data/hora relevantes, como no exemplo a seguir para tabelas particionadas mensais:
bq query --nouse_legacy_sql 'DELETE FROM my_dataset.my_table WHERE TIMESTAMP_TRUNC(ts_column, MONTH) = "2020-01-01 00:00:00";'
Ou outro exemplo para tabelas particionadas com a coluna DATETIME
:
bq query --nouse_legacy_sql 'DELETE FROM my_dataset.my_table WHERE dt_column BETWEEN DATETIME("2020-01-01") AND DATETIME("2020-05-01");'
Como usar uma instrução MERGE
Use uma instrução DML MERGE
para combinar operações INSERT
, UPDATE
e DELETE
de uma tabela particionada em uma única instrução e executá-las de maneira atômica.
Como remover partições ao usar uma instrução MERGE
Ao executar uma instrução MERGE
em uma tabela particionada, você pode limitar
quais partições são verificadas incluindo a coluna de particionamento
em um filtro de subconsulta, um filtro search_condition
ou um filtro merge_condition
.
A remoção pode ocorrer ao verificar a tabela de origem, a tabela de destino ou ambas.
Cada um dos exemplos abaixo consulta uma tabela particionada por tempo de processamento usando
a pseudocoluna _PARTITIONTIME
como filtro.
Como usar uma subconsulta para filtrar dados de origem
Na instrução MERGE
a seguir, a subconsulta na cláusula USING
filtra
a pseudocoluna _PARTITIONTIME
na tabela de origem.
MERGE dataset.target T USING (SELECT * FROM dataset.source WHERE _PARTITIONTIME = '2018-01-01') S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED THEN DELETE
Analisando o plano de execução da consulta, a subconsulta é executada primeiro. Somente as linhas na
partição '2018-01-01'
na tabela de origem são verificadas. Veja a
etapa relevante no plano de consulta:
READ $10:name, $11:_PARTITIONTIME
FROM temp.source
WHERE equal($11, 1514764800.000000000)
Como usar um filtro na search_condition
de uma when_clause
Se um search_condition
contiver um filtro, o otimizador de consulta tentará
remover partições. Por exemplo, na instrução MERGE
a seguir, cada cláusula WHEN
MATCHED
e WHEN NOT MATCHED
contém um filtro na pseudocoluna
_PARTITIONTIME
.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-01' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-02' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID + 10 WHEN NOT MATCHED BY SOURCE AND T._PARTITIONTIME = '2018-01-03' THEN DELETE
Durante o estágio de junção, apenas as seguintes partições são verificadas na tabela
de destino: '2018-01-01'
, '2018-01-02'
e '2018-01-03'
, ou seja, a
união de todos os filtros search_condition
.
No plano de execução da consulta:
READ
$1:COLUMN_ID, $2:_PARTITIONTIME, $3:$file_temp_id, $4:$row_temp_id
FROM temp.target
WHERE or(equal($2, 1514764800.000000000), equal($2, 1514851200.000000000), equal($2, 1514937600.000000000))
No entanto, no exemplo a seguir, a cláusula WHEN NOT MATCHED BY SOURCE
não tem uma expressão de filtro:
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-01' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID WHEN NOT MATCHED BY SOURCE THEN UPDATE SET COLUMN_ID = COLUMN_ID + 1
Essa consulta precisa verificar toda a tabela de destino para calcular a cláusula WHEN NOT MATCHED BY
SOURCE
. Como resultado, nenhuma partição é removida.
Como usar um predicado falso constante em um merge_condition
Se você usar as cláusulas WHEN NOT MATCHED
e WHEN NOT MATCHED BY SOURCE
juntas, o BigQuery geralmente executará uma junção externa completa, que
não pode ser removida. No entanto, se a condição de mesclagem usar um predicado falso
constante, o BigQuery poderá usar a condição de filtro para
remover a partição. Para mais informações sobre o uso de predicados falsos
constantes, consulte a descrição da cláusula merge_condition
na
documentação da
instrução MERGE
.
O exemplo a seguir verifica somente a partição '2018-01-01'
nas tabelas de destino
e de origem.
MERGE dataset.target T USING dataset.source S ON FALSE WHEN NOT MATCHED AND _PARTITIONTIME = '2018-01-01' THEN INSERT(COLUMN_ID) VALUES(COLUMN_ID) WHEN NOT MATCHED BY SOURCE AND _PARTITIONTIME = '2018-01-01' THEN DELETE
Como usar um filtro em uma merge_condition
O otimizador de consulta tenta usar um filtro em uma merge_condition
para remover partições. O otimizador de consulta pode ou não conseguir executar o push-down
do predicado na etapa de verificação da tabela, dependendo do tipo de junção.
No exemplo a seguir, o merge_condition
é usado como um predicado para unir
as tabelas de origem e de destino. O otimizador de consulta pode executar o push-down desse predicado
ao verificar ambas as tabelas. Como resultado, a consulta apenas verifica
a partição '2018-01-01'
nas tabelas de destino e de origem.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID AND T._PARTITIONTIME = '2018-01-01' AND S._PARTITIONTIME = '2018-01-01' WHEN MATCHED THEN UPDATE SET COLUMN_ID = NEW_VALUE
No próximo exemplo, merge_condition
não contém um predicado para a
tabela de origem. Portanto, não é possível executar a remoção da partição na tabela de origem. A
instrução contém um predicado para a tabela de destino, mas a instrução usa
uma cláusula WHEN NOT MATCHED BY SOURCE
em vez de uma cláusula WHEN MATCHED
. Isso
significa que a consulta precisa verificar toda a tabela de destino em busca das linhas que não
corresponderem.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID AND T._PARTITIONTIME = '2018-01-01' WHEN NOT MATCHED BY SOURCE THEN UPDATE SET COLUMN_ID = NEW_VALUE
Limitações
Para informações sobre as limitações da DML, consulte Limitações na página Referência da DML.
Cotas
Para informações sobre as cotas de DML, consulte Instruções DML na página Cotas e limites.
Preços
Para saber mais sobre os preços para DML, consulte Preços da DML para tabelas particionadas.
Segurança de tabelas
Para controlar o acesso a tabelas no BigQuery, consulte Introdução aos controles de acesso a tabelas.
A seguir
- Saiba como criar tabelas particionadas.
- Saiba como consultar tabelas particionadas.
- Veja uma introdução à DML
- Saiba como compor instruções DML usando a sintaxe DML.