Os nós ODPS Script permitem desenvolver tarefas do MaxCompute no modo script usando o mecanismo SQL do MaxCompute V2.0. Nesse modo, o sistema compila um arquivo de script SQL inteiro — incluindo múltiplas instruções — como uma única unidade e o envia ao MaxCompute como um plano de execução. Todas as instruções são executadas em uma única fila, o que permite ao MaxCompute otimizar o processamento entre as instruções e utilizar totalmente os recursos disponíveis.
Pré-requisitos
Antes de começar, verifique se você tem:
Um nó ODPS Script criado no DataWorks. Para mais detalhes, consulte Criar e gerenciar nós ODPS.
Quando usar o modo script
Use o modo script quando precisar:
Reescrever uma única instrução com subconsultas aninhadas em várias instruções mais simples que compartilham resultados intermediários.
Dividir um script complexo em várias instruções conectadas por variáveis.
O modo script não é adequado quando dados de múltiplas origens apresentam grandes intervalos de tempo entre suas disponibilidades. Por exemplo, se a origem A estiver pronta às 01:00 e a origem B às 07:00, as variáveis de tabela não conseguirão agrupar essas instruções eficientemente em um único script.
Para mais informações conceituais, consulte SQL no modo script.
Sintaxe do script
Um script do MaxCompute pode conter instruções SET, DDL e DML. Cada tipo pode aparecer zero ou mais vezes, mas não é permitido misturar os tipos de instrução.
A estrutura geral é:
-- SET statements
set odps.sql.type.system.odps2=true;
[set odps.stage.reducer.num=***;]
[...]
-- DDL statements
create table table1 xxx;
[create table table2 xxx;]
[...]
-- DML statements
@var1 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table3
[WHERE where_condition];
@var2 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table4
[WHERE where_condition];
@var3 := SELECT [ALL | DISTINCT] var1.select_expr, var2.select_expr, ...
FROM @var1 join @var2 on ...;
INSERT OVERWRITE|INTO TABLE [PARTITION (partcol1=val1, partcol2=val2 ...)]
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM @var3;
[@var4 := SELECT [ALL | DISTINCT] var1.select_expr, var.select_expr, ... FROM @var1
UNION ALL | UNION
SELECT [ALL | DISTINCT] var1.select_expr, var.select_expr, ... FROM @var2;
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
AS
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM var4;]
Sintaxe de variáveis
Atribua resultados de consulta a uma variável usando o operador :=:
@<variable_name> := <SELECT statement>;
|
Elemento |
Descrição |
|
|
Nome da variável prefixado com |
|
|
Operador de atribuição. Atribui o resultado do SELECT à variável como um conjunto de resultados de tabela. |
|
|
Qualquer instrução SELECT válida. |
Para atribuir uma constante a uma variável e usá-la como valor escalar, combine SELECT <constant> com um SELECT * FROM @variable subsequente. Por exemplo:
@a := SELECT 10; -- Assign the constant 10 to @a. You can also use SELECT col1 FROM t1 to assign a value from a single-row table.
@b := SELECT key, value + (SELECT * FROM @a) FROM t2 WHERE key > 10000;
SELECT * FROM @b;
Para obter mais informações sobre essa sintaxe, consulte Subconsultas.
Limitações
As seguintes limitações se aplicam ao escrever código para nós ODPS Script.
Tipos de instrução suportados
Os nós ODPS Script suportam instruções SET, DML e um subconjunto de instruções DDL. Instruções DDL que exibem resultados — como DESC e SHOW — não são suportadas.
Instruções de exibição de resultados
Escreva no máximo uma instrução de exibição de resultados (como uma instrução SELECT) por script. Incluir múltiplas instruções desse tipo causa erro.
Erro:
SELECT * FROM src1;
SELECT * FROM src2; -- Second result-displaying statement causes an error.
Correção: Mantenha apenas um SELECT de exibição de resultados ou evite totalmente o uso de instruções SELECT de exibição em scripts de produção.
CREATE TABLE AS
Inclua no máximo uma instrução CREATE TABLE AS por script e posicione-a como a última instrução. Para manter a manutenibilidade dos scripts, escreva instruções CREATE TABLE e INSERT em seções separadas.
Comportamento em caso de falha do script
Se qualquer instrução dentro de um script falhar, todo o script falhará.
Geração de jobs
O MaxCompute gera um job para o script somente após todos os dados de entrada estarem prontos.
Escrita e leitura subsequente no mesmo script
Gravar dados em uma tabela e depois lê-los no mesmo script causa erro.
Erro:
insert overwrite table src2 select * from src where key > 0;
@a := select * from src2; -- Reading from the table written above causes an error.
select * from @a;
Correção: Use uma variável para armazenar o resultado intermediário em vez de gravar e ler a mesma tabela:
@a := select * from src where key > 0;
insert overwrite table src2 select * from @a;
select * from @a;
Exemplo básico
O script a seguir faz junção de várias tabelas de origem e grava os resultados em duas tabelas de destino. Os resultados intermediários são armazenados em variáveis, eliminando a necessidade de gerenciar manualmente a ordem de execução das instruções.
create table if not exists dest(key string, value bigint);
create table if not exists dest2(key string, value bigint);
@a := select * from src where value > 0;
@b := select * from src2 where key is not null;
@c := select * from src3 where value is not null;
@d := select a.key, b.value from @a left outer join @b on a.key = b.key and b.value > 0;
@e := select a.key, c.value from @a inner join @c on a.key = c.key;
@f := select * from @d union select * from @e union select * from @a;
insert overwrite table dest select * from @f;
@g := select e.key, c.value from @e join @c on e.key = c.key;
insert overwrite table dest2 SELECT * from @g;
Este exemplo usasrc,src2esrc3como tabelas de origem. Para criá-las com dados de amostra:
create table if not exists src(key string, value BIGINT);
insert into src values ('1', 11);
insert into src values ('1', 11);
create table if not exists src2(key string, value BIGINT);
insert into src2 values ('1', 22);
insert into src2 values ('2', 22);
create table if not exists src3(key string, value BIGINT);
insert into src3 values ('1', 33);
insert into src3 values ('3', 33);
Após a execução do script, dest contém a união de todas as linhas filtradas e unidas, enquanto dest2 contém as linhas resultantes da junção interna entre @e e @c.
Exemplos avançados
Instrução IF com expressão BOOLEAN
Quando a condição IF é uma expressão do tipo BOOLEAN, o ramo é determinado no momento da compilação do código. O MaxCompute avalia a condição durante a compilação e seleciona o ramo antes do envio do job.
set odps.sql.allow.fullscan=true;
set odps.optimizer.cbo.rule.filter.black=LM;
@date := '${var}';
@row TABLE(key int, value bigint); -- Declare a table variable with schema (key int, value bigint).
IF (cast(@date as bigint) % 2 == 0) BEGIN
@row := SELECT key, value from src1;
END ELSE BEGIN
@row := SELECT key, value from src2;
END
INSERT OVERWRITE TABLE dest1 partition(p='${var}') SELECT key, value FROM @row;
A variável var usada no script deve receber um valor na seção Scheduling Parameter da aba Properties .
Quando var é 2 (um número par), o MaxCompute seleciona o ramo src1 em tempo de compilação e insere linhas de src1 em dest1. Quando var é 3 (um número ímpar), ele insere linhas de src2 em seu lugar.
Instrução IF com subconsulta escalar do tipo BOOLEAN
Quando a condição IF é uma subconsulta escalar do tipo BOOLEAN, o ramo é determinado no tempo de execução do job, e não na compilação. O MaxCompute precisa enviar múltiplos jobs para avaliar a condição.
@i bigint;
@t table(id bigint, value bigint);
IF ((SELECT count(*) FROM src WHERE a = '5') > 1) BEGIN
@i := 1;
@t := select @i, @i*2;
END ELSE
BEGIN
@i := 2;
@t := select @i, @i*2;
END
select id, value from @t;
Se src contiver mais de uma linha onde a = '5', o script define @i como 1 e @t como (1, 2). Caso contrário, define @i como 2 e @t como (2, 4).
UDFs embutidas no código
O modo script suporta a incorporação de código Java ou Python diretamente em um script SQL para implementar funções definidas pelo usuário (UDFs). Para mais detalhes, consulte UDFs embutidas no código.
Próximos passos
Após concluir o desenvolvimento do nó, siga as etapas abaixo para colocar a tarefa em produção.
|
Etapa |
Descrição |
|
Configure agendamento |
Defina o comportamento de reexecução, ciclos de agendamento e dependências de tarefas para que o DataWorks execute a tarefa conforme programado. Consulte Visão geral. |
|
Depurar o nó |
Execute o código no DataWorks para validar sua lógica antes da implantação. Se a saída não corresponder ao esperado, corrija o código e execute novamente. Consulte Procedimento de depuração. |
|
Implantar o nó |
Implante o nó para ativar o agendamento periódico com base nas propriedades configuradas. Após a implantação, o DataWorks agenda a tarefa automaticamente. Consulte Implantar nós. |