Este tópico descreve como modifique instruções SQL incompatíveis.
Informações básicas
O MaxCompute V2.0 adota totalmente o ecossistema open source, com suporte a mais recursos de linguagem e maior velocidade de execução. No entanto, essa versão aplica verificações de sintaxe mais rigorosas. Consultas com sintaxe imprecisa executadas com sucesso em versões anteriores do compilador podem gerar erros no MaxCompute V2.0.
group.by.with.star
Descrição: Este problema ocorre ao usar uma instrução select * …group by….
No MaxCompute V2.0, a lista
GROUP BYdeve incluir todas as colunas da tabela de origem. Caso contrário, ocorrerá um erro.Versões anteriores do MaxCompute aceitavam a sintaxe
select * from ... group by keymesmo quando a listaGROUP BYnão continha todas as colunas da tabela de origem.
Exemplos
-
Cenário 1: A chave GROUP BY não inclui todas as colunas da tabela de origem.
-
Sintaxe incorreta
select * from t group by key; -
Mensagem de erro
FAILED: ODPS-0130071:[1,8] Semantic analysis exception - column reference t.value should appear in GROUP BY key -
Sintaxe correta
select distinct key from t;
-
-
Cenário 2: A chave GROUP BY inclui todas as colunas.
-
A sintaxe abaixo não é recomendada.
select * from t group by key, value; -- t has columns key and value -
Embora essa sintaxe não gere erro no MaxCompute V2.0, recomenda-se alterar a instrução conforme mostrado a seguir.
select distinct key, value from t;
-
bad.escape
Descrição: Este problema refere-se a sequências de escape incorretas.
Segundo as regras do MaxCompute, use uma barra invertida seguida de um número octal de três dígitos para representar caracteres ASCII de 0 a 127 em um literal de string. Por exemplo, "\001" e "\002" representam 0 e 1, respectivamente. Contudo, versões anteriores também processavam \01 e \0001 como \001.
Esse comportamento pode causar confusão. Não é possível usar "\0001" para representar "\000" seguido de "1". Para usuários que migram de outros sistemas, isso também pode resultar em erros de integridade dos dados.
Adicionar um número após \000, como \0001 - \0009 ou \00001, pode retornar um erro.
O MaxCompute V2.0 resolve essa questão. Modifique as sequências incorretas em seus scripts.
-
Sintaxe incorreta
select split(key, "\01"), value like "\0001" from t; -
Mensagem de erro
FAILED: ODPS-0130161:[1,19] Parse exception - unexpected escape sequence: 01 ODPS-0130161:[1,38] Parse exception - unexpected escape sequence: 0001 -
Sintaxe correta
select split(key, "\001"), value like "\001" from t;
column.repeated.in.creation
Descrição: No MaxCompute V2.0, ocorre um erro se você usar nomes de coluna duplicados durante a criação de uma tabela.
Exemplo
-
Sintaxe incorreta
create table t (a BIGINT, b BIGINT, a BIGINT); -
Mensagem de erro
FAILED: ODPS-0130071:[1,37] Semantic analysis exception - column repeated in creation: a -
Sintaxe correta
create table t (a BIGINT, b BIGINT);
string.join.double
Descrição: Este problema surge em uma condição JOIN na qual o lado esquerdo do sinal de igual é do tipo STRING e o lado direito é do tipo DOUBLE.
Versões anteriores do MaxCompute convertiam ambos os lados para o tipo
BIGINT. Essa conversão podia causar perda significativa de precisão. Por exemplo, a condição de junção1.1="1"era considerada verdadeira.Para garantir compatibilidade com o Hive, o MaxCompute V2.0 converte ambos os lados para o tipo
DOUBLE.
Exemplo
-
Não recomendado
select * from t1 join t2 on t1.double_value = t2.string_value; -
Mensagem de aviso
WARNING:[1,48] implicit conversion from STRING to DOUBLE, potential data loss, use CAST function to suppress -
Sintaxe recomendada
select * from t1 join t2 on t.double_value = cast(t2.string_value as double);
window.ref.prev.window.alias
Descrição: Este problema acontece quando uma função de janela referencia um alias de outra função de janela na mesma lista SELECT.
Exemplo
-
Se
rnnão existir emt1, a sintaxe a seguir estará incorreta.select row_number() over (partition by c1 order by c1) rn, row_number() over (partition by c1 order by rn) rn2 from t1; -
Mensagem de erro
FAILED: ODPS-0130071:[2,45] Semantic analysis exception - column rn cannot be resolved -
Sintaxe correta
select row_number() over (partition by c1 order by rn) rn2 from (select c1, row_number() over (partition by c1 order by c1) rn from t1 ) tmp;
select.invalid.token.after.star
Descrição: Em uma lista SELECT, o asterisco (*) selecione todas as colunas de uma tabela. Entretanto, não é permitido adicionar um alias após o asterisco (). Essa restrição vale mesmo que o asterisco () se expanda para apenas uma coluna. O compilador do MaxCompute V2.0 reporta erro para essa sintaxe.
Exemplo
-
Sintaxe incorreta
select * as alias from table_test; -
Mensagem de erro
FAILED: ODPS-0130161:[1,10] Parse exception - invalid token 'as' -
Sintaxe correta
select * from table_test;
agg.having.ref.prev.agg.alias
Descrição: Esta situação ocorre quando a lista SELECT referencia o alias de uma função de agregação anterior e há uma cláusula HAVING presente.
Exemplo
-
Sintaxe incorreta
select count(c1) cnt, sum(c1) / cnt avg from t1 group by c2 having cnt > 1; -
Mensagem de erro
FAILED: ODPS-0130071:[2,11] Semantic analysis exception - column cnt cannot be resolved ODPS-0130071:[2,11] Semantic analysis exception - column reference cnt should appear in GROUP BY keyNeste exemplo,
secntnão existem na tabela de origemt1. Versões anteriores do MaxCompute não reportavam erro devido à presença da cláusulaHAVING. Já o MaxCompute V2.0 retorna um erro decolumn cannot be resolved. -
Sintaxe correta
select cnt, s, s/cnt avg from ( select count(c1) cnt, sum(c1) s from t1 group by c2 having count(c1) > 1 ) tmp;
order.by.no.limit
Descrição: Por padrão, o MaxCompute exige uma cláusula limit após uma cláusula order by para restringir a quantidade de resultados retornados. Esse requisito existe porque o order by executa uma ordenação completa, o que resulta em baixo desempenho de execução sem o uso de limit.
Exemplo
-
Sintaxe incorreta
select * from (select * from (select cast(login_user_cnt as int) as uv, '3' as shuzi from test_login_cnt where type = 'device' and type_name = 'mobile') v order by v.uv desc) v order by v.shuzi limit 20; -
Mensagem de erro
FAILED: ODPS-0130071:[4,1] Semantic analysis exception - ORDER BY must be used with a LIMIT clause
Adicione uma cláusula limit à subconsulta order by v.uv desc.
Além disso, o MaxCompute V1.0 não é rigoroso na verificação de views. É possível crie uma view em um projeto onde a validação de limit não é obrigatória definindo odps.sql.validate.orderby.limit=false.
create view table_view as select id from table_view order by id;
Para acessar esta view:
select * from table_view;
O MaxCompute V1.0 não reporta erro nesse caso. O MaxCompute V2.0 exibe a seguinte mensagem de erro:
FAILED: ODPS-0130071:[1,15] Semantic analysis exception - while resolving view xdj.xdj_view_limit - ORDER BY must be used with a LIMIT clause
generated.column.name.multi.window
Descrição: Este tópico aborda o uso de aliases gerados automaticamente.
Versões anteriores do MaxCompute geravam automaticamente um alias para cada expressão em uma instrução SELECT e o exibiam no console. Como as regras para essa geração não são garantidas e podem mudar, evite usar aliases gerados automaticamente.
O MaxCompute V2.0 emite um aviso quando aliases gerados automaticamente são usados. No momento, não é possível proibir totalmente essa prática devido ao seu uso disseminado.
Em alguns casos, as regras de geração de aliases mudam entre versões do MaxCompute. Como certos jobs online dependem desses aliases, consultas podem falhar durante atualizações ou rollbacks de versão. Se enfrentar esse problema, modifique suas consultas para especifique explicitamente os aliases das colunas desejadas.
Exemplo
-
Não recomendado
select _c0 from (select count(*) from table_name) t; -
Sintaxe recomendada:
select c from (select count(*) c from table_name) t;
non.boolean.filter
Problema ao usar uma condição de filtro não BOOLEAN.
O MaxCompute não permite conversões implícitas entre tipos Boolean e outros tipos de dados. Versões anteriores permitiam, em certos casos, o uso de BIGINT como condição de filtro. O MaxCompute V2.0 bloqueia esse comportamento. Caso seus scripts contenham tais condições, modifique-as. Veja um exemplo:
Sintaxe incorreta:
select id, count(*) from table_name group by id having id;
Mensagem de erro:
FAILED: ODPS-0130071:[1,50] Semantic analysis exception - expect a BOOLEAN expression
A forma correta é:
select id, count(*) from table_name group by id having id <> 0;
post.select.ambiguous
Problema ao referenciar colunas com nomes conflitantes em instruções order by, cluster by, distribute by ou sort by.
Em versões anteriores do MaxCompute, o sistema selecionava por padrão a última coluna da lista SELECT como alvo da operação. O MaxCompute V2.0 reporta erro nessa situação. Modifique suas instruções conforme o exemplo:
Sintaxe incorreta:
select a, b as a from t order by a limit 10;
Mensagem de erro:
FAILED: ODPS-0130071:[1,34] Semantic analysis exception - a is ambiguous, can be both t.a or null.a
A correção adequada é:
select a as c, b as a from t order by a limit 10;
Essa alteração abrange também casos em que há conflito de nomes, mas a semântica permanece a mesma. Embora não cause ambiguidade direta, um aviso é emitido para incentivar a correção, pois essa sintaxe tende a gerar erros facilmente.
duplicated.partition.column
Problema ao especifique partições com o mesmo nome em uma consulta.
Versões anteriores do MaxCompute não reportavam erro ao especifique chaves de partição com nomes idênticos; o valor da chave posterior simplesmente sobrescrevia o da anterior. Esse comportamento gerava confusão. O MaxCompute V2.0 passa a reportar erro nesses casos. Os exemplos a seguir ilustram o problema:
Sintaxe incorreta 1:
insert overwrite table partition (ds = '1', ds = '2')select ... ;
Durante a execução, ds = ‘1’ é ignorado.
A forma correta é:
insert overwrite table partition (ds = '2')select ... ;
Sintaxe incorreta 2:
create table t (a bigint, ds string) partitioned by (ds string);
Procedimento correto:
create table t (a bigint) partitioned by (ds string);
order.by.col.ambiguous
Problema com alias duplicado na lista select referenciado posteriormente por uma cláusula order by.
Sintaxe incorreta:
select id, id
from table_test
order by id;
A forma correta é:
select id, id id2
from table_name
order by id;
Remova o alias duplicado antes de referenciá-lo na cláusula order by.
in.subquery.without.result
Problema em que colx é reportado como inexistente na tabela de origem se colx in subquery não retornar resultados.
Sintaxe incorreta:
select * from table_name
where not_exist_col in (select id from table_name limit 0);
Mensagem de erro:
FAILED: ODPS-0130071:[2,7] Semantic analysis exception - column not_exist_col cannot be resolved
ctas.if.not.exists
Problema com sintaxe incorreta para a tabela de destino.
Se a tabela de destino já existir, versões anteriores do MaxCompute não realizavam verificações de sintaxe. O MaxCompute V2.0 executa as validações normais, o que pode gerar diversas mensagens de erro. Veja um exemplo:
Sintaxe incorreta:
create table if not exists table_name
as
select * from not_exist_table;
Mensagem de erro:
FAILED: ODPS-0130131:[1,50] Table not found - table meta_dev.not_exist_table cannot be resolved
worker.restart.instance.timeout
Em versões anteriores do MaxCompute, cada registro gerado por uma User-Defined Function (UDF) acionava uma operação de escrita no sistema de arquivos distribuído e enviava um heartbeat ao Fuxi. Se a UDF não produzisse resultados por 10 minutos, a seguinte mensagem de erro aparecia:
FAILED: ODPS-0123144: Fuxi job failed - WorkerRestart errCode:252,errMsg:kInstanceMonitorTimeout, usually caused by bad udf performance.
O framework de runtime do MaxCompute V2.0 suporta vetorização, processando múltiplas linhas de uma coluna simultaneamente para aumentar a eficiência. Porém, a vetorização pode causar timeout em instruções que antes rodavam sem erros. Isso ocorre se o intervalo entre a saída de dois registros for inferior a 10 minutos. Como várias linhas são processadas em lote, os heartbeats podem não ser enviados ao Fuxi a tempo.
Ao encontrar esse erro, verifique primeiro se sua UDF apresenta problemas de desempenho, como demora de vários segundos por registro. Se não for possível otimizar a UDF, tente resolver ajustando manualmente o tamanho do lote de linhas. O valor padrão é 1024.
set odps.sql.executionengine.batch.rowcount=16;
divide.nan.or.overflow
Problema em que versões anteriores do MaxCompute não aplicavam constant folding em divisões.
Por exemplo, para a instrução abaixo, o plano de execução física nas versões anteriores era:
explain
select if(false, 0/0, 1.0)
from table_name;
in task M1_Stg1:
Data source: meta_dev.table_name
TS: alias: table_name
SEL: If(False, Divide(UDFToDouble(0), UDFToDouble(0)), 1.0)
FS: output: None
Note que as funções IF e Divide permanecem. Durante a execução, a expressão Divide no segundo parâmetro não é avaliada porque o primeiro parâmetro de IF é falso, evitando exceção de divisão por zero.
Contudo, o MaxCompute V2.0 suporta constant folding para divisões e reporta erro, conforme o exemplo:
Sintaxe incorreta:
select IF(FALSE, 0/0, 1.0)
from table_name;
Mensagem de erro:
FAILED: ODPS-0130071:[1,19] Semantic analysis exception - encounter runtime exception while evaluating function /, detailed message: DIVIDE func result NaN, two params are 0.000000 and 0.000000
Além do erro acima, pode ocorrer um erro de overflow. Exemplo:
Sintaxe incorreta:
select if(false, 1/0, 1.0)
from table_name;
Mensagem de erro:
FAILED: ODPS-0130071:[1,19] Semantic analysis exception - encounter runtime exception while evaluating function /, detailed message: DIVIDE func result overflow, two params are 1.000000 and 0.000000
A forma correta é:
Elimine o uso de /0 e substitua por uma constante válida.
O constant folding de CASE WHEN apresenta problema similar. Em CASE WHEN TRUE THEN 0 ELSE 0/0, o MaxCompute V2.0 avalia todas as subexpressões durante o constant folding, causando erro de divisão por zero.
Cenários de otimização com CASE WHEN podem ser mais complexos. Exemplo:
select case when key = 0 then 0 else 1/key end
from (
select 0 as key from src
union all
select key from src) r;
O otimizador empurra a operação de divisão para dentro da subconsulta. A transformação assemelha-se a:
M (
select case when 0 = 0 then 0 else 1/0 end c1 from src
UNION ALL
select case when key = 0 then 0 else 1/key end c1 from src) r;
Mensagem de erro:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.ArithmeticException: DIVIDE func result overflow, two params are 1.000000 and 0.000000
Nesse caso, o constant folding da primeira cláusula do UNION ALL gera erro. Para corrigir, mova a cláusula CASE WHEN da instrução SQL para a subconsulta, remova a cláusula CASE WHEN desnecessária e elimine o uso de /0:
select c1 end
from (
select 0 c1 end from src
union all
select case when key = 0 then 0 else 1/key end) r;
small.table.exceeds.mem.limit
Versões anteriores do MaxCompute suportavam a otimização Multi-way Join. Múltiplas junções usando a mesma chave eram mescladas em uma única tarefa Fuxi, como J4_1_2_3_Stg1 na consulta abaixo:
explain
select t1.*
from t1 join t2 on t1.c1 = t2.c1
join t3 on t1.c1 = t3.c1;
Plano de execução física em versões anteriores do MaxCompute:
In Job job0:
root Tasks: M1_Stg1, M2_Stg1, M3_Stg1
J4_1_2_3_Stg1 depends on: M1_Stg1, M2_Stg1, M3_Stg1
In Task M1_Stg1:
Data source: meta_dev.t1
In Task M2_Stg1:
Data source: meta_dev.t2
In Task M3_Stg1:
Data source: meta_dev.t3
In Task J4_1_2_3_Stg1:
JOIN: t1 INNER JOIN unknown INNER JOIN unknown
SEL: t1._col0, t1._col1, t1._col2
FS: output: None
Ao adicionar um hint MapJoin, o plano de execução física nas versões antigas permanecia inalterado. Isso indica que versões anteriores priorizavam a otimização Multi-way Join, podendo ignorar hints MapJoin definidos pelo usuário.
explain
select /* +mapjoin(t1) */ t1.*
from t1 join t2 on t1.c1 = t2.c1
join t3 on t1.c1 = t3.c1;
O plano de execução física nas versões anteriores permanecia idêntico ao anterior.
O otimizador do MaxCompute V2.0 prioriza hints MapJoin especificados pelo usuário. No exemplo acima, se t1 for grande, pode ocorrer um erro semelhante a:
FAILED: ODPS-0010000:System internal error - SQL Runtime Internal Error: Hash Join Cursor HashJoin_REL… small table exceeds, memory limit(MB) 640, fixed memory used …, variable memory used …
Se o comportamento do MapJoin não for o esperado, remova o hint MapJoin.
sigkill.oom
Assim como no problema small.table.exceeds.mem.limit, ao especifique um hint MapJoin com uma tabela pequena que seja muito grande, a consulta podia ter sucesso em versões anteriores por ser otimizada como Multi-way Join. No MaxCompute V2.0, defina odps.sql.mapjoin.memory.max para evitar erros de limite de memória da tabela pequena. Porém, cada worker do MaxCompute possui um limite fixo de memória. Se a tabela for excessivamente grande, o worker será encerrado por erro de out-of-memory (OOM). O erro assemelha-se a:
Fuxi job failed - WorkerRestart errCode:9,errMsg:SigKill(OOM), usually caused by OOM(outof memory).
Nessa situação, remova o hint MapJoin e utilize Multi-way Join.
wm_concat.first.argument.const
A documentação de WM_CONCAT em Aggregate functions sempre exigiu que o primeiro parâmetro fosse uma constante. Versões anteriores do MaxCompute não eram rigorosas nessa verificação. Se a tabela de origem estivesse vazia, nenhum erro era reportado mesmo que o primeiro parâmetro fosse um ColumnReference.
Function declaration:
string wm_concat(string separator, string str)
Parameter description:
separator: A constant of the String type. This is the separator. Other data types or non-constants will cause an exception.
O MaxCompute V2.0 valida os parâmetros durante a fase de planejamento. Se o primeiro parâmetro de WM_CONCAT não for constante, um erro é reportado imediatamente. Exemplo:
Sintaxe incorreta:
select wm_concat(value, ',') FROM src group by value;
Mensagem de erro:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: com.aliyun.odps.lot.cbo.validator.AggregateCallValidator$AggregateCallValidationException: Invalid argument type - The first argument of WM_CONCAT must be constant string.
pt.implicit.convertion.failed
srcpt é uma tabela particionada com duas partições:
create table srcpt(key STRING, value STRING) partitioned by (pt STRING);
alter table srcpt add partition (pt='pt1');
alter table srcpt add partition (pt='pt2');
Na instrução SQL acima, a coluna pt do tipo String e as constantes do tipo INT são convertidas para DOUBLE para comparação. Mesmo com o projeto configurado como odps.sql.udf.strict.mode=true, versões anteriores não reportavam erro, filtrando todos os valores de pt. O MaxCompute V2.0 reporta erro. Exemplo:
Sintaxe incorreta:
select key from srcpt where pt in (1, 2);
Mensagem de erro:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.NumberFormatException: ODPS-0123091:Illegal type cast - In function cast, value 'pt1' cannot be casted from String to Double.
Evite comparar uma coluna de chave de partição STRING com constantes do tipo INT. Altere as constantes INT para o tipo STRING.
having.use.select.alias
A especificação SQL define que as cláusulas GROUP BY e HAVING são processadas antes da cláusula SELECT. Logo, a cláusula HAVING não pode usar um alias de coluna gerado pela cláusula SELECT.
Exemplo
-
Sintaxe incorreta:
select id id2 from table_name group by id having id2 > 0; -
Mensagem de erro:
FAILED: ODPS-0130071:[1,44] Semantic analysis exception - column id2 cannot be resolvedODPS-0130071:[1,44] Semantic analysis exception - column reference id2 should appear in GROUP BY keyNeste exemplo,
id2é um novo alias de coluna gerado na cláusulaSELECTe não pode ser usado na cláusulaHAVING.
dynamic.pt.to.static
Descrição: No MaxCompute V2.0, partições dinâmicas são ocasionalmente convertidas em partições estáticas pelo otimizador.
Exemplo
insert overwrite table srcpt partition(pt) select id, 'pt1' from table_name;
é convertido para
insert overwrite table srcpt partition(pt='pt1') select id from table_name;
Se você especifique um valor de partição inválido, como um uso incorreto de '${bizdate}', o MaxCompute V2.0 reportará erro durante a fase de verificação de sintaxe. Para mais informações, consulte Partitions.
Sintaxe incorreta:
insert overwrite table srcpt partition(pt) select id, '${bizdate}' from table_name limit 0;
Mensagem de erro:
FAILED: ODPS-0130071:[1,24] Semantic analysis exception - wrong columns count 2 in data source, requires 3 columns (includes dynamic partitions if any)
Em versões anteriores, a instrução SQL não produzia dados devido à cláusula LIMIT 0 e nenhuma partição dinâmica era criada, portanto, nenhum erro era reportado.
lot.not.in.subquery
Descrição: Este problema refere-se ao tratamento de valores NULL em subconsultas IN.
Em operações IN do SQL padrão, se a lista de valores contiver NULL, o retorno nunca será false, podendo ser apenas NULL ou true. Por exemplo, 1 in (null, 1, 2, 3) retorna true, 1 in (null, 2, 3) retorna NULL e null in (null, 1, 2, 3) retorna NULL. Analogamente, em operações NOT IN, se a lista contiver NULL, o retorno será apenas false ou NULL, nunca true.
O MaxCompute V2.0 segue o comportamento do SQL padrão. Ao receber este aviso, verifique se a subconsulta na operação IN pode retornar valores nulos e confirme se o comportamento resultante atende às suas expectativas. Caso contrário, faça as modificações necessárias.
Exemplo
-
Se a coluna
acceptednão contiver valoresNULL, ignore este aviso. Se houver valores nulos, a instruçãoc not in (select accepted from c_list), que antes retornavatrue, agora retornaráNULLno MaxCompute V2.0.select * from t where c not in (select accepted from c_list); -
Sintaxe correta
select * from t where c not in (select accepted from c_list where accepted is not null)