O MaxCompute permite usar INSERT INTO ou INSERT OVERWRITE para inserir ou sobrescrever dados em uma tabela de destino ou partição estática.
Execute os comandos deste tópico nas seguintes plataformas:
Pré-requisitos
Para executar operações INSERT INTO e INSERT OVERWRITE, é necessária a permissão Update na tabela de destino e a permissão Select na tabela source. Para mais informações sobre como conceder permissões, consulte MaxCompute Permissions.
Visão geral
Ao processar dados com MaxCompute SQL, use a instrução INSERT INTO ou INSERT OVERWRITE para salvar o resultado de uma consulta SELECT em uma tabela de destino. As diferenças são:
INSERT INTO: Adiciona dados a uma tabela ou partição estática. Especifique valores de partição na instruçãoINSERTpara inserir dados em uma partição específica. Para inserir um pequeno volume de dados de teste, combine esta instrução com VALUES.-
INSERT OVERWRITE: Limpa os dados existentes em uma tabela ou partição estática antes de inserir os novos dados.NotaA sintaxe
INSERTdo MaxCompute difere da sintaxeINSERTdo MySQL ou Oracle. Omita a palavra-chaveTABLEtanto nas instruçõesINSERT INTOquanto nasINSERT OVERWRITE.Ao executar repetidamente uma operação
INSERT OVERWRITEna mesma partição, oSizeda partição retornado pelo comandoDESCpode variar. Isso ocorre porque, ao executarSELECTdos dados de uma partição e depois usarINSERT OVERWRITEpara gravá-los de volta na mesma partição, a lógica de divisão de arquivos muda. Consequentemente, oSizedos dados também se altera. O comprimento total dos dados permanece o mesmo antes e depois da operaçãoINSERT OVERWRITE, sem gerar custos extras de armazenamento.
Para obter informações sobre como inserir dados em partições dinâmicas, consulte Insert or overwrite data in dynamic partitions (DYNAMIC PARTITION).
Limitações
-
As seguintes limitações se aplicam ao usar
INSERT INTOeINSERT OVERWRITEpara atualizar dados em uma tabela ou partição estática:INSERT INTO: Não é possível adicionar dados a uma tabela clusterizada.INSERT OVERWRITE: Não oferece suporte à especificação de colunas para inserção. Para especificar colunas, useINSERT INTO. Por exemplo, a instruçãoCREATE TABLE t(a STRING, b STRING); INSERT INTO t(a) VALUES ('1');insere '1' na coluna a e define a coluna b como NULL ou seu valor padrão.O MaxCompute não implementa bloqueios de tabela. Evite executar operações
INSERT INTOouINSERT OVERWRITEsimultaneamente na mesma tabela.
-
As restrições abaixo se aplicam a uma Delta Table.
Ao usar
INSERT OVERWRITEpara gravar dados em uma Delta Table, várias linhas com o mesmo valor de PK são deduplicadas antes da gravação. Apenas a primeira linha é gravada. O resultado final depende da ordem dos registros durante o processo de computação, que não pode ser especificada manualmente. Como essa operação grava todo o conjunto de dados, essa deduplicação padrão ajuda a garantir a unicidade da chave primária.Ao gravar dados em uma Delta Table usando
INSERT INTO, várias linhas com o mesmo valor de chave primária (PK) não são deduplicadas por padrão; todas são gravadas na tabela. No entanto, se você definirset odps.sql.insert.acidtable.deduplicate.enable = true, os dados serão deduplicados antes da gravação.
Sintaxe
INSERT {INTO|OVERWRITE} TABLE <table_name> [PARTITION (<pt_spec>)] [(<col_name> [,<col_name> ...)]]
<select_statement>
FROM <from_statement>
[ZORDER BY <zcol_name> [, <zcol_name> ...]];
A tabela a seguir descreve os parâmetros.
Parâmetro | Obrigatório | Descrição |
table_name | Sim | Nome da tabela de destino onde os dados serão inseridos. |
pt_spec | Não | Partição na qual os dados serão inseridos. Especifique uma constante. Funções e expressões não são permitidas. O formato é |
col_name | Não | Nome da coluna na tabela de destino onde os dados serão inseridos.
|
select_statement | Sim | Cláusula Nota
|
from_statement | Sim | Cláusula |
ZORDER BY <zcol_name> [, <zcol_name> ...] | Não | Ao gravar dados em uma tabela ou partição, classifique os dados por uma ou mais colunas especificadas (colunas na tabela correspondentes ao select_statement) para agrupar linhas com dados semelhantes. Isso melhora o desempenho de filtragem de consultas e pode reduzir custos de armazenamento. Observe que |
As diferenças entre ZORDER BY e SORT BY são:
-
ZORDER BYpossui dois modos: zorder local e zorder global. O modo padrão élocal zorder. O modo local classifica os dados por z-order apenas dentro de arquivos individuais e não redistribui os dados globalmente. Portanto, se os dados estiverem distribuídos por vários arquivos, o clustering de dados pode ser baixo, o que impede o Data Skipping eficaz. Para resolver esse problema, versões mais recentes oferecem suporte aglobal zorder. Para usar o modoglobal zorder, defina o seguinte parâmetro:SET odps.sql.default.zorder.type=global;.ZORDER BYapresenta as seguintes limitações:Para tabelas particionadas, execute uma classificação
ZORDER BYem apenas uma partição por vez.A contagem de colunas do
ZORDER BYdeve estar entre 2 e 4.Se a tabela de destino for clusterizada, a cláusula
ZORDER BYnão será suportada.ZORDER BYpode ser usado comDISTRIBUTE BY, mas não pode ser combinado comORDER BY,CLUSTER BYouSORT BY.
NotaAo gravar dados usando a cláusula
ZORDER BY, a operação consome mais recursos e leva mais tempo do que sem a classificação. A instrução
SORT BYespecifica como os dados são classificados dentro de um único arquivo. Se você não especificarSORT BY, os dados dentro de um único arquivo serão classificados porlocal zorder.
Exemplos: tabelas regulares
-
Exemplo 1: Execute o comando
INSERT INTOpara adicionar dados à tabela não particionadawebsites. Comando:--Create a non-partitioned table named websites. CREATE TABLE IF NOT EXISTS websites (id INT, name STRING, url STRING ); --Create a non-partitioned table named apps. CREATE TABLE IF NOT EXISTS apps (id INT, app_name STRING, url STRING ); --Append data to the apps table. The keyword TABLE in `INSERT INTO TABLE ` is optional. INSERT INTO apps (id,app_name,url) VALUES (1,'Aliyun','https://www.aliyun.com'); --Copy data from the apps table and append it to the websites table. INSERT INTO websites (id,name,url) SELECT id,app_name,url FROM apps; --Run the SELECT statement to view the data in the websites table. SELECT * FROM websites;Resultado retornado:
-- The result. +------------+------------+------------+ | id | name | url | +------------+------------+------------+ | 1 | Aliyun | https://www.aliyun.com | +------------+------------+------------+ -
Exemplo 2: Use o comando
INSERT INTOpara adicionar dados à tabela particionadasale_detail. Exemplo de comando:-- Create a partitioned table named sale_detail. CREATE TABLE IF NOT EXISTS sale_detail ( shop_name STRING, customer_id STRING, total_price DOUBLE ) PARTITIONED BY (sale_date STRING, region STRING); -- Add a partition to the source table. This step is optional. If the partition does not exist, it is automatically created when you write data. ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china'); -- Append data to the source table. The TABLE keyword after INSERT INTO and INSERT OVERWRITE is optional. INSERT INTO sale_detail PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3); -- Enable a full table scan for the current session only. Run a SELECT statement to view data in the sale_detail table. SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail;Resultado retornado:
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | s1 | c1 | 100.1 | 2013 | china | | s2 | c2 | 100.2 | 2013 | china | | s3 | c3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+ -
Exemplo 3: Execute o comando
INSERT OVERWRITEpara sobrescrever dados na tabelasale_detail_insert. Exemplo de comando:-- Create a target table named sale_detail_insert with the same schema as sale_detail. CREATE TABLE sale_detail_insert LIKE sale_detail; -- Add a partition to the target table. This step is optional. If the partition does not exist, it is automatically created when you write data. ALTER TABLE sale_detail_insert ADD PARTITION (sale_date='2013', region='china'); -- Overwrite a static partition. For static partitions, partition columns are specified in the PARTITION() clause and must not be in the SELECT list. The columns in the SELECT list are mapped to the target table's columns by position. SET odps.sql.allow.fullscan=true; INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT shop_name, customer_id, total_price FROM sale_detail ZORDER BY customer_id, total_price; -- Enable a full table scan for the current session only. Run a SELECT statement to view data in the sale_detail_insert table. SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail_insert;Resultado retornado:
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | s1 | c1 | 100.1 | 2013 | china | | s2 | c2 | 100.2 | 2013 | china | | s3 | c3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+ -
Exemplo 4: Execute o comando
INSERT OVERWRITEpara sobrescrever dados na tabelasale_detail_inserte alterar a ordem das colunas na cláusulaSELECT. O mapeamento entre a tabela source e a tabela de destino baseia-se na ordem das colunas na cláusulaSELECT, e não nos nomes das colunas. Comando:SET odps.sql.allow.fullscan=true; INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT customer_id, shop_name, total_price FROM sale_detail; SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail_insert;Resultado retornado:
+------------+-------------+-------------+------------+------------+ | shop_name | customer_id | total_price | sale_date | region | +------------+-------------+-------------+------------+------------+ | c1 | s1 | 100.1 | 2013 | china | | c2 | s2 | 100.2 | 2013 | china | | c3 | s3 | 100.3 | 2013 | china | +------------+-------------+-------------+------------+------------+Quando a tabela
sale_detail_insertfoi criada, a ordem das colunas era:+-------------------+--------------------+-------------------+ | shop_name STREING | customer_id STRING| total_price BIGINT| +-------------------+--------------------+-------------------+A ordem de inserção de dados de
sale_detailemsale_detail_inserté a seguinte:+---------------------+--------------------+-------------------+ | customer_id STRING | shop_name STREING | total_price BIGINT| +---------------------+--------------------+-------------------+Neste caso, os dados de
sale_detail.customer_idsão inseridos emsale_detail_insert.shop_name, e os dados desale_detail.shop_namesão inseridos emsale_detail_insert.customer_id. -
Exemplo 5: Ao inserir dados em uma partição, as colunas de partição não podem aparecer na cláusula
SELECT. A instrução a seguir retorna um erro porquesale_dateeregionsão colunas de partição, proibidas na cláusulaSELECTpara uma partição estática. Exemplo de comando incorreto:INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date='2013', region='china') SELECT shop_name, customer_id, total_price, sale_date, region FROM sale_detail; -
Exemplo 6: O valor de
PARTITIONdeve ser uma constante, não uma expressão. Exemplo de comando incorreto:INSERT OVERWRITE TABLE sale_detail_insert PARTITION (sale_date=datepart('2016-09-18 01:10:00', 'yyyy') , region='china') SELECT shop_name, customer_id, total_price FROM sale_detail; -
Exemplo 7: Execute o comando
INSERT OVERWRITEpara sobrescrever dados nas tabelasmf_srcemf_zorder_srce classificar a tabelamf_zorder_srcno modo zorder global. Exemplo de comando:-- Create the target table mf_src. CREATE TABLE mf_src (key STRING, value STRING); INSERT OVERWRITE TABLE mf_src SELECT a, b FROM VALUES ('1', '1'),('3', '3'),('2', '2') AS t(a, b); SELECT * FROM mf_src; -- The result is returned: +-----+-------+ | key | value | +-----+-------+ | 1 | 1 | | 3 | 3 | | 2 | 2 | +-----+-------+ -- Create the target table mf_zorder_src with the same schema as mf_src. CREATE TABLE mf_zorder_src LIKE mf_src; -- Use the global z-order mode for sorting. SET odps.sql.default.zorder.type=global; INSERT OVERWRITE TABLE mf_zorder_src SELECT key, value FROM mf_src ZORDER BY key, value; SELECT * FROM mf_zorder_src;Resultado retornado:
+-----+-------+ | key | value | +-----+-------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +-----+-------+ -
Exemplo 8: Execute o comando
INSERT OVERWRITEpara sobrescrever os dados na tabelatargetexistente. Comando:-- The 'target' table is an existing table. SET odps.sql.default.zorder.type=global; INSERT OVERWRITE TABLE target SELECT key, value FROM target ZORDER BY key, value;
Exemplos: Delta Table
Exemplo: Crie a Delta Table mf_dt e execute o comando INSERT para inserir e sobrescrever dados.
-- Create a Delta Table named mf_dt.
CREATE TABLE IF NOT EXISTS mf_dt (pk BIGINT NOT NULL PRIMARY KEY,
val BIGINT NOT NULL)
PARTITIONED BY (dd STRING, hh STRING)
tblproperties ("transactional"="true");
-- Insert test data into the partition where dd='01' and hh='01' in the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='01')
VALUES (1, 1), (2, 2), (3, 3);
-- Query data in the target partition of the mf_dt table.
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT INTO' to append data to the target partition of the mf_dt table.
INSERT INTO TABLE mf_dt PARTITION(dd='01', hh='01')
VALUES (3, 30), (4, 4), (5, 5);
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 30 | 01 | 01 |
| 4 | 4 | 01 | 01 |
| 5 | 5 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT OVERWRITE' to overwrite data in the target partition of the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='01')
VALUES (1, 1), (2, 2), (3, 3);
SELECT * FROM mf_dt WHERE dd='01' AND hh='01';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
-- Use 'INSERT OVERWRITE' to write data to the partition where dd='01' and hh='02' in the mf_dt table.
INSERT OVERWRITE TABLE mf_dt PARTITION (dd='01', hh='02')
VALUES (1, 11), (2, 22), (3, 32);
SELECT * FROM mf_dt WHERE dd='01' AND hh='02';
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 11 | 01 | 02 |
| 3 | 32 | 01 | 02 |
| 2 | 22 | 01 | 02 |
+------------+------------+----+----+
-- Enable a full table scan for the current session only. Run a SELECT statement to view data in the mf_dt table.
SET odps.sql.allow.fullscan=true;
SELECT * FROM mf_dt;
-- The result is returned:
+------------+------------+----+----+
| pk | val | dd | hh |
+------------+------------+----+----+
| 1 | 11 | 01 | 02 |
| 3 | 32 | 01 | 02 |
| 2 | 22 | 01 | 02 |
| 1 | 1 | 01 | 01 |
| 3 | 3 | 01 | 01 |
| 2 | 2 | 01 | 01 |
+------------+------------+----+----+
Melhores práticas
O Z-ordering não é adequado para todos os cenários. Teste seu caso de uso para determinar se os benefícios de armazenamento e desempenho de consulta justificam o custo computacional adicional de gravar dados com Z-order. As seções a seguir fornecem recomendações gerais.
Escolher um índice clusterizado em vez de Z-order
Se suas condições de filtro forem tipicamente baseadas em um prefixo de colunas, como
a,a and boua and b and c, usar um índice clusterizado (por exemplo,ORDER BY a, b, c) é mais eficaz. Não useZORDER BYneste caso. Isso ocorre porqueORDER BYfornece excelente classificação para a primeira coluna, com menor impacto nas colunas subsequentes. Em contraste,ZORDER BYdá peso igual a todas as colunas especificadas, tornando a classificação em qualquer coluna individual menos eficiente do que a classificação na primeira coluna de uma cláusulaORDER BY.Caso certas colunas apareçam frequentemente em uma chave
JOIN, Hash ou Range Clustering é mais adequado. A implementação de Z-order do MaxCompute classifica dados apenas dentro de arquivos, e o mecanismo SQL não tem conhecimento da distribuição de dados Z-order. No entanto, o mecanismo SQL reconhece um índice clusterizado e pode otimizar melhor o desempenho doJOINdurante a fase de planejamento da consulta.Se você executa frequentemente operações
GROUP BYeORDER BYem determinadas colunas, usar um índice clusterizado pode oferecer melhor desempenho.
Recomendações de Z-order
Selecione colunas que aparecem frequentemente nas condições de filtro, especialmente aquelas filtradas em conjunto.
Quanto mais colunas você incluir no
ZORDER BY, menos eficaz será a classificação para cada coluna individual. Portanto, não especifique mais de quatro colunas. Se houver apenas uma coluna, use um índice clusterizado em vez de Z-ordering.Prefira colunas com cardinalidade equilibrada (número de valores distintos). Colunas de baixa cardinalidade, como uma coluna de gênero, oferecem benefício mínimo de classificação. Colunas de alta cardinalidade com valores majoritariamente únicos aumentam os custos de classificação, pois a implementação de Z-order do MaxCompute precisa armazenar em cache todos os valores distintos na memória para calcular o valor Z.
O tamanho da tabela não deve ser nem muito pequeno nem muito grande. Se o volume de dados for muito pequeno, os benefícios do Z-ordering não ficam evidentes. Se o volume de dados for muito grande, o custo de geração de dados com Z-order pode ser alto, impactando significativamente o tempo de conclusão das tarefas de linha de base.