Saiba como criar, ler e gravar tabelas externas para dados CSV e TSV armazenados no Object Storage Service (OSS).
Observações de uso
Tabelas externas do OSS não suportam a propriedade de cluster.
O tamanho de um único arquivo não pode exceder 2 GB. É necessário dividir arquivos maiores que 2 GB.
O MaxCompute e o OSS devem estar na mesma região.
Tipos de dados suportados
Para obter mais informações sobre os tipos de dados do MaxCompute, consulte Data Type Version 1.0 e Data Type Version 2.0.
Para obter mais informações sobre o SmartParse, consulte Flexible type compatibility of Smart Parse.
Tipo | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (Integrado) | org.apache.hadoop.hive.serde2.OpenCSVSerde (Código aberto) |
TINYINT | ||
SMALLINT | ||
INT | ||
BIGINT | ||
BINARY | ||
FLOAT | ||
DOUBLE | ||
DECIMAL(precision,scale) | ||
VARCHAR(n) | ||
CHAR(n) | ||
STRING | ||
DATE | ||
DATETIME | ||
TIMESTAMP | ||
TIMESTAMP_NTZ | ||
BOOLEAN | ||
ARRAY | ||
MAP | ||
STRUCT | ||
JSON |
Formatos de compactação suportados
Ao ler ou gravar em arquivos compactados do OSS, inclua o atributo with serdeproperties na instrução CREATE TABLE. Para obter mais informações, consulte with serdeproperties attribute parameters.
Formato de compactação | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (Integrado) | org.apache.hadoop.hive.serde2.OpenCSVSerde (Código aberto) |
GZIP | ||
SNAPPY | ||
LZO | ||
ZSTD |
Evolução de esquema suportada
Operação | Suportada | Descrição |
Adicionar coluna |
| |
Remover coluna | Esta operação não é recomendada, pois pode causar incompatibilidade entre o esquema e os dados. | |
Alterar ordem das colunas | Esta operação não é recomendada, pois pode causar incompatibilidade entre o esquema e os dados. | |
Alterar tipo de dados da coluna | Para obter uma lista de conversões de tipos de dados suportadas, consulte Change Column Data Type. | |
Renomear coluna | ||
Modificar comentário da coluna | O comentário deve ser uma string válida com comprimento máximo de 1.024 bytes. Caso contrário, ocorrerá um erro. | |
Alterar nulabilidade da coluna | Esta operação não é suportada. As colunas aceitam valores nulos por padrão. |
Configuração de parâmetros
O esquema de uma tabela externa CSV ou TSV mapeia as colunas do arquivo por posição. Se o número de colunas em um arquivo do OSS não corresponder ao número de colunas no esquema da tabela externa, use o parâmetro odps.sql.text.schema.mismatch.mode para especificar como lidar com linhas incompatíveis.
-
Se
odps.sql.text.schema.mismatch.modeestiver definido como truncate, as modificações nas colunas terão os seguintes efeitos:Os dados que estão em conformidade com o novo esquema são lidos conforme esperado.
-
Os dados existentes que usam o esquema antigo são lidos com base no novo esquema.
Por exemplo, se você adicionar uma coluna a uma tabela, os dados históricos dessa coluna aparecerão como NULL durante a leitura.
-
Se
odps.sql.text.schema.mismatch.modeestiver definido como ignore, as modificações nas colunas terão os seguintes efeitos:Os dados que estão em conformidade com o novo esquema são lidos conforme esperado.
-
Os dados existentes que usam o esquema antigo são lidos com base no novo esquema.
Por exemplo, se você adicionar uma coluna a uma tabela, linhas inteiras de dados históricos sem a nova coluna serão descartadas durante a leitura.
-
Se
odps.sql.text.schema.mismatch.modeestiver definido como error, as modificações nas colunas terão os seguintes efeitos:Os dados que estão em conformidade com o novo esquema são lidos conforme esperado.
-
Os dados existentes que usam o esquema antigo são lidos com base no novo esquema.
Por exemplo, se você adicionar uma coluna a uma tabela, ocorrerá um erro ao tentar ler dados históricos sem a nova coluna.
Descrição de permissões
Ao acessar tabelas externas do OSS, o acesso aos dados ocorre por meio da função especificada no parâmetro
odps.properties.rolearn, independentemente de você usar uma conta Alibaba Cloud, um usuário RAM ou uma função RAM. Portanto, crie uma função RAM e conceda a ela permissões para acessar o bucket do OSS de destino. Em seguida, configure o ARN da função no parâmetroodps.properties.rolearn. Para obter mais informações, consulte Parameters.Autorize o acesso na mesma conta ou entre contas, conforme seus requisitos de negócios. Recomendamos o uso de uma política de autorização personalizada para um controle de acesso mais refinado. Para obter mais informações, consulte Authorization for external data sources.
Criar uma tabela externa
Sintaxe
Analisador de texto integrado
Formato CSV
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
STORED BY 'com.aliyun.odps.CsvStorageHandler'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];
Formato TSV
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
STORED BY 'com.aliyun.odps.TsvStorageHandler'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];
Analisador de código aberto integrado
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
[WITH serdeproperties (
['<property_name>'='<property_value>',...]
)]
STORED AS TEXTFILE
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];
Parâmetros comuns
Para obter mais informações sobre parâmetros comuns, consulte Basic syntax parameters.
Parâmetros específicos de formato
Parâmetros WITH SERDEPROPERTIES
Analisador aplicável | Parâmetro | Caso de uso | Descrição | Valor | Padrão |
Analisador de dados de texto integrado (CsvStorageHandler/TsvStorageHandler) | odps.text.option.gzip.input.enabled | Use esta propriedade para ler arquivos CSV ou TSV compactados no formato GZIP. | Propriedade de compactação CSV e TSV. Defina esta propriedade como |
| False |
odps.text.option.gzip.output.enabled | Use esta propriedade para gravar dados no OSS no formato compactado GZIP. | Propriedade de compactação CSV e TSV. Defina esta propriedade como |
| False | |
odps.text.option.header.lines.count | Use esta propriedade para ignorar as primeiras N linhas de um arquivo CSV ou TSV no OSS. | Especifica o número de linhas de cabeçalho a serem ignoradas desde o início do arquivo durante a leitura dos dados. | Inteiro não negativo | 0 | |
odps.text.option.null.indicator | Use esta propriedade para definir uma string personalizada que representa um valor NULL nos dados. | O MaxCompute analisa a string especificada como um valor Por exemplo, para interpretar | string | string vazia | |
odps.text.option.ignore.empty.lines | Use esta propriedade para definir como lidar com linhas vazias em um arquivo CSV ou TSV. | Se |
| True | |
odps.text.option.encoding | Use esta propriedade quando um arquivo de dados não utilizar a codificação UTF-8 padrão. | A codificação especificada aqui deve corresponder à codificação real do arquivo. Uma incompatibilidade causa falhas na leitura. |
| UTF-8 | |
odps.text.option.delimiter | Use esta propriedade para especificar o delimitador de coluna para arquivos CSV ou TSV. | Garanta que o delimitador especificado separe corretamente as colunas no seu arquivo de dados para evitar desalinhamento. | Caractere único | Vírgula (,) | |
odps.text.option.use.quote | Use esta propriedade quando um campo em um arquivo CSV ou TSV contiver quebras de linha (CRLF), aspas duplas ou o delimitador de coluna. | Quando um campo em um arquivo CSV contém uma nova linha, aspas duplas (é necessário adicionar outra |
| False | |
odps.sql.text.option.flush.header | Use esta propriedade para gravar um cabeçalho de tabela como a primeira linha em cada bloco de arquivo no OSS. | Esta propriedade aplica-se apenas a arquivos CSV. |
| False | |
odps.sql.text.schema.mismatch.mode | Use esta propriedade quando uma linha no arquivo de dados tiver um número de colunas diferente do esquema da tabela externa. | Especifica como lidar com linhas cuja contagem de colunas não corresponde ao esquema da tabela. Nota: Este recurso não funciona se |
| error | |
odps.text.option.zstd.input.enabled | Use esta propriedade para ler arquivos CSV ou TSV compactados no formato ZSTD. | Propriedade de compactação CSV e TSV. Defina esta propriedade como True para que o MaxCompute leia arquivos compactados em ZSTD. Caso contrário, a operação de leitura falhará. |
| False | |
odps.text.option.zstd.output.enabled | Use esta propriedade para gravar dados no OSS no formato compactado ZSTD. | Propriedade de compactação CSV e TSV. Defina esta propriedade como True para compactar dados no formato ZSTD ao gravar no OSS. Caso contrário, os dados serão gravados sem compactação. |
| False | |
odps.text.option.snappy.input.enabled | Adicione esta propriedade quando precisar ler arquivos CSV ou TSV compactados com SNAPPY (SnappyRawCodec). | Propriedade de compactação CSV e TSV. O MaxCompute só consegue ler arquivos compactados quando este parâmetro está definido como True. Caso contrário, a operação de leitura falhará. |
| False | |
odps.text.option.snappy.output.enabled | Adicione esta propriedade quando precisar gravar dados no OSS compactados com SNAPPY (SnappyRawCodec). | Propriedade de compactação CSV e TSV. Quando este parâmetro está definido como True, o MaxCompute grava dados no OSS com compactação SNAPPY. Caso contrário, os dados são gravados sem compactação. |
| False | |
Analisador de dados de código aberto integrado (OpenCSVSerde) | separatorChar | Use esta propriedade para especificar o delimitador de coluna para dados CSV armazenados como TEXTFILE. | Especifica o delimitador de coluna. | Um caractere único | Vírgula (,) |
quoteChar | Use esta propriedade quando campos em dados CSV contiverem caracteres especiais, como o delimitador ou quebras de linha. | Especifica o caractere usado para colocar campos entre aspas. | Um caractere único | Nenhum | |
escapeChar | Use esta propriedade para especificar o caractere de escape para dados CSV armazenados como TEXTFILE. | Especifica o caractere usado para escapar caracteres especiais dentro de um campo. | Um caractere único | Nenhum |
Parâmetros tblproperties
Analisador aplicável | Parâmetro | Caso de uso | Descrição | Valor | Padrão |
Analisador de dados de código aberto integrado (OpenCSVSerde) | skip.header.line.count | Use esta propriedade para ignorar as primeiras N linhas de um arquivo CSV armazenado como TEXTFILE. | Especifica o número de linhas de cabeçalho a serem ignoradas desde o início do arquivo durante a leitura dos dados. | Inteiro não negativo | Nenhum |
skip.footer.line.count | Use esta propriedade para ignorar as últimas N linhas de um arquivo CSV armazenado como TEXTFILE. | Especifica o número de linhas de rodapé a serem ignoradas no final do arquivo durante a leitura dos dados. | Inteiro não negativo | Nenhum | |
mcfed.mapreduce.output.fileoutputformat.compress | Use esta propriedade para gravar dados TEXTFILE no OSS com compactação. | Propriedade de compactação TEXTFILE. Se definido como |
| False | |
mcfed.mapreduce.output.fileoutputformat.compress.codec | Use esta propriedade para especificar o codec de compactação ao gravar dados TEXTFILE compactados no OSS. Ao ler arquivos CSV/TSV compactados cujos nomes contenham o sufixo .bz2, .deflate, .snappy, .gz ou .zstd, nenhuma configuração adicional é necessária. | Propriedade de compactação TEXTFILE. Define o método de compactação para arquivos de dados TEXTFILE. |
| Nenhum | |
odps.text.option.bad.row.skipping | Use esta propriedade para ignorar dados incorretos em arquivos CSV armazenados no OSS. | Controla se o MaxCompute ignora linhas consideradas dados incorretos ou relata um erro. |
| Nenhum |
Lista de permissões e lista de bloqueios
As tabelas externas do OSS no MaxCompute suportam filtragem por lista de permissões e lista de bloqueios. Ao definir parâmetros de lista de permissões e lista de bloqueios em tblproperties, filtre quais arquivos ler de um diretório. Para obter detalhes, consulte Whitelist and blacklist.
Gravar dados
Para obter detalhes sobre a sintaxe de gravação no MaxCompute, consulte Write syntax.
Consulta e análise
Consulte Query syntax para obter detalhes sobre a sintaxe SELECT.
Consulte Query optimization para obter detalhes sobre a otimização de planos de consulta.
Consulte BadRowSkipping para obter detalhes.
BadRowSkipping
O recurso BadRowSkipping permite ignorar linhas inválidas em dados CSV que, de outra forma, causariam falha na consulta. Esta configuração controla o tratamento de erros e não afeta a análise do formato de dados subjacente.
Parâmetros
-
Parâmetro de nível de tabela:
odps.text.option.bad.row.skippingrigid: Força a ignorância de linhas. Esta configuração não pode ser substituída por configurações de nível de sessão ou projeto.flexible: Habilita a ignorância de linhas. Esta configuração é flexível, permitindo que seja substituída por configurações de nível de sessão ou projeto.
-
Parâmetros de nível de
session/project-
O parâmetro
odps.sql.unstructured.text.bad.row.skippingpode substituir um parâmetro de nível de tabelaflexible, mas não um parâmetrorigid.on: Habilita o recurso. Se o recurso não estiver configurado para a tabela, ele será habilitado por padrão.off: Desabilita o recurso. Se a tabela estiver configurada como flexible, o recurso será desabilitado. Caso contrário, a configuração do parâmetro da tabela será usada.<null> or invalid input: A configuração de nível de tabela é usada.
-
odps.sql.unstructured.text.bad.row.skipping.debug.num: Especifica o número de resultados de erro a serem impressos no stdout no Logview.O valor máximo é 1000.
Se o valor for <=0, este recurso será desabilitado.
Se o valor for inválido, este recurso será desabilitado.
-
-
Interação entre parâmetros de nível de sessão e propriedades da tabela
tbl property
session flag
resultado
rigid
on
On, Forçado on
off
<null>, um valor inválido ou o parâmetro não está configurado
flexible
on
On
off
Off, Desabilitado pela sessão
<null>, um valor inválido ou o parâmetro não está configurado
On
Não configurado
on
On, Habilitado pela sessão
off
Off
<null>, um valor inválido ou o parâmetro não está configurado
Exemplos
-
Prepare os dados
Faça upload do arquivo de dados de teste csv_bad_row_skipping.csv, que contém linhas inválidas, para um diretório no OSS, como
oss-mc-test/badrow/. -
Crie as tabelas externas CSV
Os exemplos a seguir mostram três cenários baseados em diferentes combinações de parâmetros de nível de tabela e nível de sessão.
Parâmetro da tabela:
odps.text.option.bad.row.skipping = flexible | rigid | <not set>Flag da sessão:
odps.sql.unstructured.text.bad.row.skipping = on | off | <not set>
Parâmetro não definido
-- No table-level parameter is set. Queries will fail on bad rows unless overridden by the session-level flag. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flag ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>';Ignorância flexível
-- The table is configured to skip bad rows, but this can be disabled by the session-level flag. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flexible ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'flexible' -- Enables flexible skipping, which can be disabled at the session level. );Ignorância rígida
-- The table is configured to forcibly skip bad rows. This cannot be disabled at the session level. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_rigid ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'rigid' -- Forces skipping on. ); -
Verifique os resultados da consulta
Parâmetro não definido
-- The following command enables skipping, but it is immediately overridden by the next command in this example. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command disables skipping and is the active setting for the SELECT query below, causing it to fail. SET odps.sql.unstructured.text.bad.row.skipping=off; -- You can use this command to print details of skipped rows when skipping is enabled. It has no effect here because the query fails. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flag;A consulta falha com o seguinte erro: FAILED: ODPS-0123131:User defined function exception
Ignorância flexível
-- The following command enables skipping, but it is immediately overridden by the next command in this example. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command disables skipping, overriding the table's 'flexible' setting. It is the active setting for the SELECT query below, causing it to fail. SET odps.sql.unstructured.text.bad.row.skipping=off; -- Print details of up to 10 bad rows at the session level. The maximum is 1,000. A value of 0 or less disables printing. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flexible;A consulta falha com o seguinte erro: FAILED: ODPS-0123131:User defined function exception
Ignorância rígida
-- This command is redundant because the 'rigid' setting already enforces skipping. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command attempts to disable skipping, but it is ignored because the 'rigid' table setting cannot be overridden. SET odps.sql.unstructured.text.bad.row.skipping=off; -- This command prints details for up to 10 bad rows that are skipped by the 'rigid' setting. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_rigid;O seguinte resultado é retornado:
+------------+------------+ | a | b | +------------+------------+ | 1 | 26 | | 5 | 37 | +------------+------------+
Compatibilidade de tipos flexível com Smart Parse
Para tabelas externas formatadas em CSV no OSS, o SQL do MaxCompute usa o tipo de dados 2.0 para operações de leitura e gravação. Anteriormente, apenas valores em formatos estritos eram suportados. Este recurso oferece compatibilidade flexível de tipos para ler uma ampla variedade de formatos de valores de arquivos CSV. As regras específicas de análise são detalhadas abaixo.
Tipo | Entrada como string | Saída como string | Descrição |
BOOLEAN |
Nota Uma operação |
| A análise falha se a string de entrada não for um dos valores suportados. |
TINYINT |
Nota
|
| Inteiro de 8 bits. Ocorre um erro se o valor estiver fora do intervalo |
SMALLINT | Inteiro de 16 bits. Ocorre um erro se o valor estiver fora do intervalo | ||
INT | Inteiro de 32 bits. Ocorre um erro se o valor estiver fora do intervalo | ||
BIGINT | Inteiro de 64 bits. Ocorre um erro se o valor estiver fora do intervalo Nota O valor | ||
FLOAT |
Nota
|
| Valores especiais (sem distinção entre maiúsculas e minúsculas) incluem NaN, Inf, -Inf, Infinity e -Infinity. Ocorre um erro se um valor estiver fora do intervalo. Se a precisão exceder o limite, o valor será arredondado. |
DOUBLE |
Nota
|
| Valores especiais (sem distinção entre maiúsculas e minúsculas) incluem NaN, Inf, -Inf, Infinity e -Infinity. Ocorre um erro se um valor estiver fora do intervalo. Se a precisão exceder o limite, o valor será arredondado. |
DECIMAL (precision, scale) Exemplo: DECIMAL(15,2) |
Nota
|
| Ocorre um erro se a parte inteira contiver mais de Um erro é relatado. Se a parte fracionária exceder a escala, o valor será arredondado e truncado. |
CHAR(n) Exemplo: CHAR(7) |
|
| O comprimento máximo é 255. Se uma string de entrada for menor que n, ela será preenchida com espaços à direita, mas esses espaços são ignorados nas comparações. Se uma string de entrada for maior que n, ela será truncada. |
VARCHAR(n) Exemplo: VARCHAR(7) |
|
| O comprimento máximo é 65.535. Se uma string de entrada for maior que n, ela será truncada. |
STRING |
|
| O comprimento máximo é 8 MB. |
DATE |
Nota Você também pode definir a propriedade |
|
|
TIMESTAMP_NTZ Nota O OpenCsvSerde não suporta este tipo porque é incompatível com o formato de dados Hive. |
|
|
|
DATETIME |
| Supondo que o fuso horário do sistema seja Asia/Shanghai:
|
|
TIMESTAMP |
| (Supondo que o fuso horário do sistema seja Asia/Shanghai)
|
|
-
Regras gerais
Para qualquer tipo de dados, uma string vazia no arquivo de dados CSV é analisada como NULL ao ser lida em uma tabela.
-
Tipos de dados não suportados
Tipos complexos (STRUCT, ARRAY, MAP): Não suportados. Valores desses tipos frequentemente contêm caracteres como a vírgula (
,), que podem entrar em conflito com delimitadores CSV comuns e causar falhas na análise.BINARY e INTERVAL: Atualmente não suportados. Se você precisar de suporte para esses tipos, entre em contato com o suporte técnico do MaxCompute.
-
Tipos numéricos (INT, DOUBLE, etc.)
Para tipos de dados numéricos como INT, SMALLINT, TINYINT, BIGINT, FLOAT, DOUBLE e DECIMAL, o MaxCompute oferece amplas capacidades de análise padrão.
Se você precisar analisar apenas strings numéricas básicas, defina a propriedade
odps.text.option.smart.parse.levelcomonaiveemtblproperties. No modo naive, o analisador suporta apenas formatos simples como "123" e "123.456". A análise de outros formatos de string causa um erro.
-
Tipos de data e hora (DATE, TIMESTAMP, etc.)
A classe
java.time.format.DateTimeFormatterprocessa todos os quatro tipos de data e hora:DATE, DATETIME, TIMESTAMP e TIMESTAMP_NTZ.Formatos padrão: O MaxCompute possui vários formatos de análise integrados.
-
Formatos personalizados:
Defina múltiplos formatos de análise e um formato de saída configurando a propriedade
odps.text.option.<date|datetime|timestamp|timestamp_ntz>.io.formatemtblproperties.Use o símbolo de cerquilha (
#) para separar múltiplos padrões de análise.Formatos personalizados têm precedência sobre os formatos integrados. O primeiro padrão personalizado é usado para saída.
Exemplo: Se você definir a string de formato personalizado para o tipo DATE como
pattern1#pattern2#pattern3, o MaxCompute poderá analisar strings que correspondam apattern1,pattern2oupattern3. No entanto, ao gravar dados em um arquivo, a saída sempre usará o formato especificado porpattern1. Para obter mais informações, consulte DateTimeFormatter.
-
Nota importante sobre o padrão de fuso horário 'z'
Evite usar 'z' (nome do fuso horário) em formatos personalizados, especialmente para usuários na China, pois é ambíguo.
Em vez disso, use 'x' (deslocamento de zona) ou 'VV' (ID do fuso horário) para o padrão de fuso horário.
Exemplo: 'CST' normalmente significa China Standard Time (UTC+8) na China. No entanto, quando
java.time.format.DateTimeFormatteranalisa 'CST', ele interpreta como US Central Standard Time (UTC-6), o que pode causar resultados inesperados de entrada ou saída.
Lógica de divisão de arquivos CSV
O analisador CSV/TSV integrado (OpenCSVSerde)
O analisador CSV/TSV integrado (OpenCSVSerde) exige que cada linha de dados em um arquivo CSV seja separada por \r\n ou caracteres semelhantes, e as colunas não devem conter \r\n. A lógica de divisão paralela e integridade de dados é a seguinte:
Primeiro, o arquivo é dividido pelo tamanho do split, e algumas linhas podem ser cortadas no meio.
Quando workers subsequentes consomem splits, todos os splits, exceto o primeiro, ignoram ativamente a linha parcial ou completa inicial.
Cada worker também deve consumir ativamente a linha parcial ou completa final, mesmo que ela caia dentro do intervalo do próximo split.
Este analisador suporta divisão paralela, mas não suporta escape de aspas.
O analisador CSV de código aberto (CsvStorageHandler / TsvStorageHandler)
O analisador CSV de código aberto (CsvStorageHandler / TsvStorageHandler) leva em consideração o escape de aspas ao ler arquivos CSV/TSV e suporta \r\n. Ele consegue lidar com cenários onde caracteres especiais, como aspas aninhadas ou \r\n, aparecem dentro de aspas.
Por exemplo, nos dados "a\ra","b\nb","cc""cc", o \r\n e as aspas duplas podem ser analisados e gerados corretamente, suportando valores entre linhas. No entanto, como as posições reais de quebra de linha só podem ser determinadas através da análise dos dados, o arquivo não pode ser simplesmente dividido por \r\n. Como resultado, o consumo paralelo de um único arquivo não é suportado.
Se você confirmar que as colunas de dados não contêm \r\n e que \r\n é usado apenas como delimitador de linha, habilite a divisão paralela definindo odps.sql.unstructured.data.single.file.split.enabled. Nesse caso, um arquivo grande pode ser dividido em vários splits pelo tamanho do split, e o Text Extractor integrado se alinha automaticamente aos limites de quebra de linha para garantir a integridade dos dados.
Conclusão:
Se os dados contiverem \r\n que não possam ser tratados como delimitador de linha, apenas o analisador CSV/TSV integrado poderá ser usado.
Por outro lado, se você precisar dividir um único arquivo grande em paralelo, apenas o analisador CSV Serde de código aberto poderá ser usado.
Exemplos
Pré-requisitos
-
Um bucket e uma pasta do OSS disponíveis. Para obter mais informações, consulte Create a bucket e Manage folders.
O MaxCompute suporta a criação automática de pastas no OSS. Se uma instrução SQL envolver tabelas externas e funções definidas pelo usuário (UDFs), use uma única instrução para ler e gravar nas tabelas e usar as UDFs. Você também pode criar pastas manualmente.
O MaxCompute é implantado apenas em regiões específicas. Para evitar possíveis problemas com conexões de dados entre regiões, garanta que seu bucket do OSS esteja na mesma região do seu projeto MaxCompute.
-
Autorização
Você deve ter permissões para acessar o OSS. Use uma conta Alibaba Cloud, um usuário Resource Access Management (RAM) ou uma função RAM para acessar tabelas externas do OSS. Para obter mais informações sobre autorização, consulte Authorize access in STS mode for OSS.
Você deve ter a permissão CreateTable no projeto MaxCompute. Para obter mais informações sobre permissões de tabela, consulte MaxCompute permissions.
Criar uma tabela externa do OSS com o analisador de texto integrado
Exemplo 1: Tabela não particionada
-
Mapeie a tabela externa para o diretório
Demo1/do sample data. Use o comando a seguir para criar uma tabela externa do OSS.CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external1 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo1/'; -- You can run the `desc extended mc_oss_csv_external1;` command to view the schema of the created OSS external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM de destino e conceda a ela as permissões necessárias para acessar o OSS. -
Consulte a tabela externa não particionada.
SELECT * FROM mc_oss_csv_external1;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 1 | 51 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 4 | 30 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | W | | 1 | 5 | 47 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 6 | 9 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | S | | 1 | 7 | 53 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | | 1 | 8 | 63 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | SW | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | | 1 | 10 | 31 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | +------------+------------+------------+------------+------------------+-------------------+------------+----------------+ -
Grave dados na tabela externa não particionada e verifique se os dados foram gravados com êxito.
INSERT INTO mc_oss_csv_external1 VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10','SW'); SELECT * FROM mc_oss_csv_external1 WHERE recordId=12;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | SW | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+Verifique se um novo arquivo aparece no diretório
Demo1/no OSS.Após a gravação dos dados, visualize o arquivo de resultado gerado
20250606054845430gpwnhakujm16_M1_1_0_0-0_TableSink1-0-.csv(0,046 KB) no caminho correspondente do OSS, juntamente com o arquivo de dados originalvehicle.csv(0,45 KB).
Exemplo 2: Tabela particionada
-
Mapeie a tabela externa para o diretório
Demo2/do sample data. O comando de exemplo a seguir cria uma tabela externa particionada do OSS.CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external2 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING ) PARTITIONED BY ( direction STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo2/'; -- You can run the `DESC EXTENDED mc_oss_csv_external2;` command to view the schema of the created external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM de destino e conceda a ela as permissões necessárias para acessar o OSS. -
Importe os dados da partição. Se você criar uma tabela externa particionada do OSS, também deverá importar os dados da partição. Para obter mais informações, consulte OSS external tables.
MSCK REPAIR TABLE mc_oss_csv_external2 ADD PARTITIONS; -- This is equivalent to the following statement. ALTER TABLE mc_oss_csv_external2 ADD PARTITION (direction = 'N') PARTITION (direction = 'NE') PARTITION (direction = 'S') PARTITION (direction = 'SW') PARTITION (direction = 'W'); -
Consulte a tabela externa particionada.
SELECT * FROM mc_oss_csv_external2 WHERE direction='NE';O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ -
Grave dados na tabela externa particionada e verifique se os dados foram gravados com êxito.
INSERT INTO mc_oss_csv_external2 PARTITION(direction='NE') VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10'); SELECT * FROM mc_oss_csv_external2 WHERE direction='NE' AND recordId=12;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+Verifique se um novo arquivo foi gerado no diretório
Demo2/direction=NEno OSS.O arquivo de dados de partição gerado automaticamente
20250606062610590gocsdsoujm16_M1_1_0_0-0_TableSink1-0-.csvpode ser visto na lista de arquivos do OSS, indicando que os dados foram gravados com êxito no caminho de partição correspondente no OSS.
Exemplo 3: Dados compactados
Este exemplo mostra como criar uma tabela externa CSV compactada em GZIP e executar operações de leitura e gravação.
-
Crie uma tabela interna e insira dados de teste para um teste de gravação subsequente.
CREATE TABLE vehicle_test( vehicleid INT, recordid INT, patientid INT, calls INT, locationlatitute DOUBLE, locationlongtitue DOUBLE, recordtime STRING, direction STRING ); INSERT INTO vehicle_test VALUES (1,1,51,1,46.81006,-92.08174,'9/14/2014 0:00','S'); -
Crie uma tabela externa CSV compactada em GZIP e mapeie-a para o diretório
Demo3/(que contém dados compactados) do sample data. O comando de exemplo a seguir cria a tabela externa do OSS.CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external3 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) PARTITIONED BY (dt STRING) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole', 'odps.text.option.gzip.input.enabled'='true', 'odps.text.option.gzip.output.enabled'='true' ) LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo3/'; -- Import partition data. MSCK REPAIR TABLE mc_oss_csv_external3 ADD PARTITIONS; -- You can run the `DESC EXTENDED mc_oss_csv_external3;` command to view the schema of the created external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM de destino e conceda a ela as permissões necessárias para acessar o OSS. -
Use um cliente MaxCompute para ler dados do OSS:
NotaSe os dados compactados no OSS estiverem em um formato de dados de código aberto, adicione o comando
set odps.sql.hive.compatible=true;antes da instrução SQL e envie-os juntos para execução.--Enable a full table scan for the current session only. SET odps.sql.allow.fullscan=true; SELECT recordId, patientId, direction FROM mc_oss_csv_external3 WHERE patientId > 25;O comando retorna o seguinte resultado:
+------------+------------+------------+ | recordid | patientid | direction | +------------+------------+------------+ | 1 | 51 | S | | 3 | 48 | NE | | 4 | 30 | W | | 5 | 47 | S | | 7 | 53 | N | | 8 | 63 | SW | | 10 | 31 | N | +------------+------------+------------+ -
Leia dados da tabela interna e grave-os na tabela externa do OSS.
Execute o comando
INSERT OVERWRITEouINSERT INTOem uma tabela externa a partir do cliente MaxCompute para gravar dados no OSS.INSERT INTO TABLE mc_oss_csv_external3 PARTITION (dt='20250418') SELECT * FROM vehicle_test;Após a execução bem-sucedida do comando, visualize o arquivo exportado no diretório do OSS.
Criar uma tabela externa com linha de cabeçalho
Crie um diretório Demo11 no bucket oss-mc-test do sample data e execute as seguintes instruções:
--Create the external table.
CREATE EXTERNAL TABLE mf_oss_wtt
(
id BIGINT,
name STRING,
tran_amt DOUBLE
)
STORED BY 'com.aliyun.odps.CsvStorageHandler'
WITH serdeproperties (
'odps.text.option.header.lines.count' = '1',
'odps.sql.text.option.flush.header' = 'true',
'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
)
LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo11/';
--Insert data.
INSERT OVERWRITE TABLE mf_oss_wtt VALUES (1, 'val1', 1.1),(2, 'value2', 1.3);
--Query data.
--When you create the table, you can define all columns as STRING. Otherwise, an error occurs when the header is read.
--Alternatively, add the 'odps.text.option.header.lines.count' = '1' parameter to the table definition to skip the header.
SELECT * FROM mf_oss_wtt;
Este exemplo usa a função RAM aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substitua aliyunodpsdefaultrole pelo nome da sua função RAM de destino e conceda a ela as permissões necessárias para acessar o OSS.
O comando retorna o seguinte resultado:
+----------+--------+------------+
| id | name | tran_amt |
+----------+--------+------------+
| 1 | val1 | 1.1 |
| 2 | value2 | 1.3 |
+----------+--------+------------+
Criar uma tabela externa com colunas incompatíveis
-
Crie um diretório
demono bucketoss-mc-testdo sample data e faça upload do arquivotest.csv. O arquivotest.csvcontém o seguinte conteúdo:1,kyle1,this is desc1 2,kyle2,this is desc2,this is two 3,kyle3,this is desc3,this is three, I have 4 columns -
Crie as tabelas externas.
-
Defina o método de tratamento para linhas com contagens de colunas inconsistentes como
TRUNCATE.-- Drop the table. DROP TABLE test_mismatch; -- Create the external table. CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch ( id string, name string, dect string, col4 string ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.sql.text.schema.mismatch.mode' = 'truncate', 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole') LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/'; -
Especifique o método de tratamento para linhas com contagens de colunas inconsistentes como
IGNORE.-- Drop the table. DROP TABLE test_mismatch01; -- Create the external table. CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch01 ( id STRING, name STRING, dect STRING, col4 STRING ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ('odps.sql.text.schema.mismatch.mode' = 'ignore') LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/'; -
Consulte os dados nas tabelas.
-
Consulte a tabela
test_mismatch.SELECT * FROM test_mismatch; --Returned result +----+-------+---------------+---------------+ | id | name | dect | col4 | +----+-------+---------------+---------------+ | 1 | kyle1 | this is desc1 | NULL | | 2 | kyle2 | this is desc2 | this is two | | 3 | kyle3 | this is desc3 | this is three | +----+-------+---------------+---------------+ -
Consulte a tabela
test_mismatch01.SELECT * FROM test_mismatch01; --Returned result +----+-------+----------------+-------------+ | id | name | dect | col4 | +----+-------+----------------+-------------+ | 2 | kyle2 | this is desc2 | this is two +----+-------+----------------+-------------+
-
-
Criar uma tabela externa com o analisador de código aberto
Este exemplo mostra como usar o analisador de código aberto integrado para criar uma tabela externa do OSS que lê um arquivo separado por vírgulas, ignorando as linhas de cabeçalho e rodapé.
-
Crie um diretório
demo-testno bucketoss-mc-testdo sample data e faça upload do arquivo test.csv.O arquivo de teste contém os seguintes dados:
1,1,51,1,46.81006,-92.08174,9/14/2014 0:00,S 1,2,13,1,46.81006,-92.08174,9/14/2014 0:00,NE 1,3,48,1,46.81006,-92.08174,9/14/2014 0:00,NE 1,4,30,1,46.81006,-92.08174,9/14/2014 0:00,W 1,5,47,1,46.81006,-92.08174,9/14/2014 0:00,S 1,6,9,1,46.81006,-92.08174,9/15/2014 0:00,S 1,7,53,1,46.81006,-92.08174,9/15/2014 0:00,N 1,8,63,1,46.81006,-92.08174,9/15/2014 0:00,SW 1,9,4,1,46.81006,-92.08174,9/15/2014 0:00,NE 1,10,31,1,46.81006,-92.08174,9/15/2014 0:00,N -
Crie a tabela externa, especifique a vírgula como separador e defina parâmetros para ignorar as linhas de cabeçalho e rodapé.
CREATE EXTERNAL TABLE ext_csv_test08 ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) ROW FORMAT serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH serdeproperties ( "separatorChar" = ",", 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) stored AS textfile location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/***/' -- Set parameters to ignore the header and footer rows. TBLPROPERTIES ( "skip.header.line.COUNT"="1", "skip.footer.line.COUNT"="1" ) ; -
Leia dados da tabela externa.
SELECT * FROM ext_csv_test08; -- The result includes 8 rows of data because the header and footer rows are ignored. +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | NE | | 1 | 4 | 30 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | W | | 1 | 5 | 47 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | | 1 | 6 | 9 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | S | | 1 | 7 | 53 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | N | | 1 | 8 | 63 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | SW | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/15/2014 0:00 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
Criar uma tabela externa CSV com tipos de tempo personalizados
Para obter detalhes sobre formatos de análise e saída para tipos de tempo personalizados em CSV, consulte Flexible type compatibility with Smart Parse.
-
Crie uma tabela externa CSV que use vários tipos de dados de tempo, como
DATE,DATETIME,TIMESTAMPeTIMESTAMP_NTZ.CREATE EXTERNAL TABLE test_csv ( col_date DATE, col_datetime DATETIME, col_timestamp TIMESTAMP, col_timestamp_ntz TIMESTAMP_NTZ ) STORED BY 'com.aliyun.odps.CsvStorageHandler' LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) TBLPROPERTIES ( 'odps.text.option.date.io.format' = 'MM/dd/yyyy', 'odps.text.option.datetime.io.format' = 'yyyy-MM-dd-HH-mm-ss x', 'odps.text.option.timestamp.io.format' = 'yyyy-MM-dd HH-mm-ss VV', 'odps.text.option.timestamp_ntz.io.format' = 'yyyy-MM-dd HH:mm:ss.SS' ); INSERT OVERWRITE test_csv VALUES(DATE'2025-02-21', DATETIME'2025-02-21 08:30:00', TIMESTAMP'2025-02-21 12:30:00', TIMESTAMP_NTZ'2025-02-21 16:30:00.123456789'); -
Após a inserção dos dados, o conteúdo do arquivo CSV é o seguinte:
02/21/2025,2025-02-21-08-30-00 +08,2025-02-21 12-30-00 Asia/Shanghai,2025-02-21 16:30:00.12 -
Consulte os dados novamente para visualizar o resultado.
SELECT * FROM test_csv;O comando retorna o seguinte resultado:
+------------+---------------------+---------------------+------------------------+ | col_date | col_datetime | col_timestamp | col_timestamp_ntz | +------------+---------------------+---------------------+------------------------+ | 2025-02-21 | 2025-02-21 08:30:00 | 2025-02-21 12:30:00 | 2025-02-21 16:30:00.12 | +------------+---------------------+---------------------+------------------------+
Perguntas frequentes
Erro de incompatibilidade de contagem de colunas
-
Sintoma
Este erro ocorre quando a contagem de colunas em uma linha de um arquivo CSV ou TSV não corresponde à definida no DDL da tabela externa. O MaxCompute relata um erro semelhante a
FAILED: ODPS-0123131:User defined function exception - Traceback:java.lang.RuntimeException: SCHEMA MISMATCH:xxx. -
Resolução
Controle como o MaxCompute lida com a incompatibilidade definindo o parâmetro
odps.sql.text.schema.mismatch.modeno nível de sessão:SET odps.sql.text.schema.mismatch.mode=error: Falha na consulta quando ocorre uma incompatibilidade de contagem de colunas. Este é o comportamento padrão.SET odps.sql.text.schema.mismatch.mode=truncate: Se uma linha tiver mais colunas do que o definido no DDL da tabela externa, as colunas extras serão descartadas. Se uma linha tiver menos colunas, as colunas ausentes serão preenchidas com NULL.