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, oferece suporte a mais recursos de linguagem e apresenta execução mais rápida. 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, um erro será gerado.Versões anteriores do MaxCompute aceitam a sintaxe
select * from ... group by keymesmo que a listaGROUP BYnão inclua 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 a seguir não é recomendada.
select * from t group by key, value; -- t has columns key and value -
Embora essa sintaxe não cause erro no MaxCompute V2.0, recomenda-se alterar a instrução conforme mostrado abaixo.
select distinct key, value from t;
-
bad.escape
Descrição: Este problema está relacionado a sequências de escape incorretas.
De acordo com as regras do MaxCompute, use uma barra invertida seguida por um número octal de três dígitos para representar caracteres ASCII de 0 a 127 em um literal de string. Por exemplo, use "\001" e "\002" para representar 0 e 1. Versões anteriores também processavam \01 e \0001 como \001.
Esse comportamento pode causar confusão. Por exemplo, não é possível usar "\0001" para representar "\000" seguido de "1". Para usuários que migram de outros sistemas, esse comportamento também pode causar erros de integridade dos dados.
Adicionar um número a \000, como \0001 - \0009 ou \00001, pode retornar um erro.
O MaxCompute V2.0 resolve esse problema. 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 ao crie 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 ocorre 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 convertem ambos os lados para o tipo
BIGINT. Essa conversão pode causar perda significativa de precisão. Por exemplo, a condição de junção1.1="1"é 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 ocorre 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 esteja 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, use um asterisco (*) para selecione todas as colunas de uma tabela. No entanto, não é permitido adicionar um alias após o asterisco (). Essa sintaxe é proibida mesmo que o asterisco () seja expandido para apenas uma coluna. O compilador do MaxCompute V2.0 relata um 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: Este problema ocorre quando a lista SELECT referencia um 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 relatavam erro devido à cláusulaHAVING. O MaxCompute V2.0 relata 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 a adição de uma cláusula limit após uma cláusula order by para limitar o número 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 uma cláusula 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. Por exemplo, é possível crie uma view em um projeto onde a verificação de limit não é necessá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 relata erro. Já o MaxCompute V2.0 relata 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 problema está relacionado ao uso de aliases gerados automaticamente.
Versões anteriores do MaxCompute geram automaticamente um alias para cada expressão em uma instrução SELECT. Esse alias é exibido no console. No entanto, as regras para geração desse alias não são garantidas e podem mudar. Portanto, evite usar aliases gerados automaticamente.
O MaxCompute V2.0 emite um aviso quando aliases gerados automaticamente são usados. Não é possível proibir essa prática no momento devido ao seu uso generalizado.
Em alguns casos, as regras para geração de aliases mudam entre versões do MaxCompute. Como alguns jobs online dependem desses aliases, essas consultas podem falhar durante uma atualização ou rollback de versão do MaxCompute. Se você encontrar esse problema, modifique suas consultas para especifique explicitamente aliases para as 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. Contudo, versões anteriores permitiam o uso de BIGINT como condição de filtro em alguns casos. O MaxCompute V2.0 não permite mais esse comportamento. Se seus scripts contiverem tais condições de filtro, 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
Correção:
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 na lista SELECT como objeto da operação. O MaxCompute V2.0 relata um erro. Modifique suas instruções. Veja um 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
Correção:
select a as c, b as a from t order by a limit 10;
Essa alteração também abrange casos em que os nomes entram em conflito, mas a semântica permanece a mesma. Embora isso não cause ambiguidade, um aviso é relatado para incentivar correções, pois essa sintaxe pode levar facilmente a erros.
duplicated.partition.column
Problema ao especifique partições com o mesmo nome em uma consulta.
Versões anteriores do MaxCompute não relatavam erro ao especifique uma chave de partição com o mesmo nome. Em vez disso, o valor da última chave sobrescrevia o valor da chave anterior. Esse comportamento podia causar confusão. O MaxCompute V2.0 relata um erro para este caso. 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.
Correção:
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 um alias duplicado na lista select referenciado posteriormente por uma cláusula order by.
Sintaxe incorreta:
select id, id
from table_test
order by id;
Correção:
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 no qual colx é relatado 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 realizam verificações de sintaxe. O MaxCompute V2.0 executa verificações normais de sintaxe. Essa mudança pode gerar muitas 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 Função Definida pelo Usuário (UDF) aciona uma operação de gravação no sistema de arquivos distribuído e envia um heartbeat para o Fuxi. Se a UDF não gerar nenhum resultado por 10 minutos, você receberá a seguinte mensagem de erro:
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. A vetorização processa várias linhas de uma coluna por vez para melhorar a eficiência de execução. No entanto, a vetorização pode fazer com que instruções anteriormente executadas sem erros atinjam o tempo limite. Esse problema pode ocorrer se o intervalo entre a saída de dois registros for inferior a 10 minutos. Como várias linhas são processadas simultaneamente, os heartbeats podem não ser enviados ao Fuxi a tempo.
Se você encontrar esse erro, verifique primeiro se sua UDF tem problemas de desempenho, como cada registro levando vários segundos para ser processado. Se não for possível otimizar o desempenho da UDF, tente resolver o problema defina manualmente o tamanho do lote de linhas. O valor padrão é 1024.
set odps.sql.executionengine.batch.rowcount=16;
divide.nan.or.overflow
Problema no qual versões anteriores do MaxCompute não realizam constant folding para divisão.
Por exemplo, para a instrução a seguir, o plano de execução física em versões anteriores do MaxCompute é o seguinte:
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
Como observado, as funções IF e Divide são mantidas. Durante a execução, a expressão Divide no segundo parâmetro não é avaliada porque o primeiro parâmetro de IF é falso. Portanto, nenhuma exceção de divisão por zero ocorre.
No entanto, o MaxCompute V2.0 suporta constant folding para divisão e relata um erro, conforme mostrado no exemplo a seguir:
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 anterior, você também pode encontrar 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
Correção:
Remova o uso de /0 e substitua-o por uma constante válida.
O constant folding de CASE WHEN apresenta um problema semelhante. Por exemplo, em CASE WHEN TRUE THEN 0 ELSE 0/0, o MaxCompute V2.0 avalia todas as subexpressões durante o constant folding. Isso causa um erro de divisão por zero.
CASE WHEN pode envolver cenários de otimização 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 move a operação de divisão para dentro da subconsulta. A transformação é semelhante à seguinte:
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
Neste caso, o constant folding para a primeira cláusula de UNION ALL relata um erro. Para resolver esse problema, mova a cláusula CASE WHEN na instrução SQL para dentro da 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 suportam a otimização Multi-way Join. Múltiplas junções que usam a mesma chave de junção são mescladas em uma única tarefa Fuxi. Um exemplo é J4_1_2_3_Stg1 na consulta a seguir:
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 uma dica MapJoin, o plano de execução física nas versões anteriores do MaxCompute não muda. Isso indica que versões anteriores priorizam a otimização Multi-way Join e podem ignorar dicas MapJoin especifique 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 do MaxCompute permanece o mesmo.
O otimizador do MaxCompute V2.0 prioriza dicas MapJoin especifique pelo usuário. No exemplo anterior, se t1 for grande, você poderá encontrar um erro semelhante ao seguinte:
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 …
Neste caso, se o comportamento de MapJoin não for o esperado, remova a dica MapJoin.
sigkill.oom
Semelhante ao problema small.table.exceeds.mem.limit, se você especifique uma dica MapJoin e a tabela pequena especifique for grande, a consulta poderá ter sucesso em versões anteriores do MaxCompute porque é otimizada como um Multi-way Join. No MaxCompute V2.0, defina odps.sql.mapjoin.memory.max para evitar erros quando a tabela pequena excede o limite de memória. No entanto, cada worker do MaxCompute tem um limite fixo de memória. Se a tabela pequena for muito grande, o worker do MaxCompute será encerrado devido a um erro de falta de memória (OOM). O erro é semelhante ao seguinte:
Fuxi job failed - WorkerRestart errCode:9,errMsg:SigKill(OOM), usually caused by OOM(outof memory).
Neste caso, remova a dica MapJoin e use um Multi-way Join.
wm_concat.first.argument.const
A descrição de WM_CONCAT em Aggregate functions sempre exigiu que o primeiro parâmetro de WM_CONCAT fosse uma constante. Versões anteriores do MaxCompute não eram rigorosas nessa verificação. Por exemplo, se a tabela de origem não tivesse dados, nenhum erro era relatado mesmo que o primeiro parâmetro de WM_CONCAT 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 verifica a validade dos parâmetros durante a fase de planejamento. Se o primeiro parâmetro de WM_CONCAT não for uma constante, um erro é relatado imediatamente. Veja um 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 que possui 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 anterior, a coluna do tipo String pt e as constantes do tipo INT são ambas convertidas para o tipo DOUBLE para comparação. Mesmo que o projeto esteja defina como odps.sql.udf.strict.mode=true, versões anteriores do MaxCompute não relatam erro. Todos os valores de pt são filtrados. O MaxCompute V2.0 relata um erro. Veja um 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 do tipo 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. Portanto, 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, o otimizador às vezes converte partições dinâmicas em partições estáticas.
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 relatará um 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 do MaxCompute, a instrução SQL não gera dados devido à cláusula LIMIT 0, e nenhuma partição dinâmica é criada. Portanto, nenhum erro é relatado.
lot.not.in.subquery
Descrição: Este problema está relacionado ao tratamento de valores NULL em uma subconsulta IN.
Em operações IN do SQL padrão, se a lista de valores contiver NULL, o valor retornado não é false. O valor retornado só pode ser 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. Da mesma forma, para uma operação NOT IN, se a lista contiver NULL, o valor retornado será apenas false ou NULL, e nunca true.
O MaxCompute V2.0 trata esse problema com base no comportamento do SQL padrão. Se você receber este lembrete, visualize suas consultas para determinar se a subconsulta na operação IN pode retornar valores nulos. Verifique se o comportamento é o esperado quando valores nulos ocorrem. Caso contrário, faça as modificações necessárias.
Exemplo
-
Se a coluna
acceptednão contiver valoresNULL, ignore este problema. Se a coluna contiver valores nulos, a instruçãoc not in (select accepted from c_list), que anteriormente retornavatrue, agora retornaNULLno 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)