As tabelas externas Parquet permitem consultar e gravar arquivos Parquet armazenados no OSS diretamente do MaxCompute, sem carregar dados em tabelas internas.
Restrições
Tabelas externas do OSS não suportam a propriedade de cluster.
Um único arquivo não pode exceder 2 GB. Divida os arquivos que ultrapassarem esse limite.
O MaxCompute e o OSS devem estar na mesma região.
Modos de análise
O MaxCompute oferece dois modos para analisar arquivos Parquet. Defina o modo antes de executar consultas ou operações de gravação.
|
Modo |
Flag |
Implementação |
Suporte |
|
Modo JNI |
|
Implementação open-source baseada em Java |
Leitura e gravação |
|
Modo nativo |
|
Implementação nativa baseada em C++ |
Somente leitura |
Tipos de dados suportados
Para obter uma descrição completa dos tipos de dados do MaxCompute, consulte Versão 1.0 de tipos de dados e Versão 2.0 de tipos de dados.
|
Tipo de dado |
Modo JNI (leitura/gravação) |
Modo nativo (somente leitura) |
|
TINYINT |
Suportado |
Suportado |
|
SMALLINT |
Suportado |
Suportado |
|
INT |
Suportado |
Suportado |
|
BIGINT |
Suportado |
Suportado |
|
BINARY |
Suportado |
Suportado |
|
FLOAT |
Suportado |
Suportado |
|
DOUBLE |
Suportado |
Suportado |
|
DECIMAL(precision,scale) |
Não suportado |
Suportado |
|
VARCHAR(n) |
Suportado |
Suportado |
|
CHAR(n) |
Suportado |
Suportado |
|
STRING |
Suportado |
Suportado |
|
DATE |
Suportado |
Suportado |
|
DATETIME |
Suportado |
Suportado |
|
TIMESTAMP |
Suportado |
Suportado |
|
TIMESTAMP_NTZ |
Não suportado |
Não suportado |
|
BOOLEAN |
Suportado |
Suportado |
|
ARRAY |
Suportado |
Suportado |
|
MAP |
Suportado |
Suportado |
|
STRUCT |
Suportado |
Suportado |
|
JSON |
Não suportado |
Não suportado |
Formatos de compactação suportados
Tabelas externas Parquet aceitam compactação ZSTD, SNAPPY e GZIP. Para usar compactação, adicione a cláusula with serdeproperties à instrução CREATE EXTERNAL TABLE. Consulte Parâmetros with serdeproperties para mais detalhes.
Evolução de schema
As tabelas externas Parquet mapeiam os valores das colunas por nome, não por posição. Assim, você pode adicionar, excluir ou reordenar colunas com segurança, sem interromper a leitura dos dados existentes.
A coluna Data compatibility abaixo indica se a tabela consegue ler dados existentes gravados antes da alteração do schema.
|
Operação |
Suportada |
Descrição |
Compatibilidade de dados |
|
Adicionar coluna |
Sim |
Novas colunas são inseridas ao final da tabela. Não é possível especificar a posição. Valores padrão aplicam-se apenas aos dados gravados pelo MaxCompute após a alteração. |
Compatível para novos dados. Linhas históricas retornam NULL para a nova coluna. |
|
Excluir coluna |
Sim |
Como o Parquet mapeia colunas por nome, remover uma coluna do schema da tabela não afeta a leitura de arquivos existentes. |
Compatível |
|
Reordenar colunas |
Sim |
O mapeamento por nome do Parquet faz com que a ordem das colunas no DDL não precise corresponder à do arquivo. |
Compatível |
|
Alterar tipo de dado da coluna |
Não |
O Parquet aplica validação rigorosa de tipos no nível do arquivo. Alterar o tipo de uma coluna no DDL não reescreve os arquivos subjacentes, causando incompatibilidade de tipos na leitura. |
Não aplicável |
|
Renomear coluna |
Não |
Devido ao mapeamento por nome, renomear uma coluna no DDL quebra o vínculo com todos os arquivos existentes que ainda utilizam o nome original. |
Não aplicável |
|
Atualizar comentário da coluna |
Sim |
Os comentários devem ser strings válidas com no máximo 1.024 bytes. |
Compatível |
|
Alterar nulabilidade da coluna |
Não |
As colunas aceitam valores nulos por padrão. A alteração da nulabilidade não é suportada. |
Não aplicável |
Crie uma tabela externa
Dica: Caso desconheça a estrutura de colunas dos seus arquivos Parquet, use a Consulta sem schema para explorar o schema do arquivo antes de escrever o DDL.
Comportamento em caso de divergência de schema
Quando o schema do arquivo Parquet difere do DDL da tabela externa:
Fewer columns in the file than in the DDL: As colunas ausentes retornam NULL.
Mais colunas no arquivo do que no DDL: As colunas excedentes são ignoradas.
Incompatibilidade de tipo de coluna: A leitura falha com o erro
ODPS-0123131:User defined function exception - Traceback:xxx. Alinhe os tipos de coluna no DDL com o schema real do arquivo Parquet para resolver o problema.
Sintaxe
Use a sintaxe simplificada quando não houver necessidade de compactação ou ajustes de desempenho. Use a sintaxe detalhada para configurar compactação e outras opções específicas do Parquet.
Estrutura de sintaxe simplificada
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
(
<col_name> <data_type>,
...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)]
STORED AS parquet
LOCATION '<oss_location>'
[tblproperties ('<tbproperty_name>'='<tbproperty_value>', ...)];
Sintaxe detalhada
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.ql.io.parquet.serde.ParquetHiveSerDe'
WITH serdeproperties(
'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
'mcfed.parquet.compression'='ZSTD/SNAPPY/GZIP'
)
STORED AS parquet
LOCATION '<oss_location>';
Para parâmetros comuns compartilhados entre tipos de tabelas externas do OSS, consulte Parâmetros básicos de sintaxe.
Parâmetros específicos
Parâmetros with serdeproperties
Use WITH serdeproperties para configurar compactação e desempenho de leitura durante a criação da tabela. Essas configurações aplicam-se tanto a operações de leitura quanto de gravação.
|
Parâmetro |
Quando adicionar |
Descrição |
Valor |
Padrão |
|
|
Ao gravar dados Parquet no OSS em formato compactado |
Define o codec de compactação. Dados Parquet não são compactados por padrão. |
|
Nenhum |
|
|
Quando |
Nível de compactação ZSTD. Valores mais altos aumentam a taxa de compactação, mas reduzem o throughput de gravação. Para E/S Parquet em grande escala, use níveis de 3 a 5. |
1–22 |
3 |
|
|
Para melhorar o desempenho de leitura do OSS |
Tamanho do cache para arquivos de dados do OSS, em KB. |
|
Nenhum |
|
|
Para melhorar o desempenho de leitura do OSS em arquivos maiores que 1.024 KB |
Tamanho do buffer para arquivos de dados do OSS, em KB. |
|
Nenhum |
Parâmetros tblproperties
Use tblproperties para controlar a nomenclatura dos arquivos de saída, a compactação e o comportamento de gravação. Essas configurações persistem como propriedades da tabela e são aplicadas no momento da gravação.
O parâmetromcfed.parquet.compressionaparece tanto emserdepropertiesquanto emtblproperties. Useserdepropertiespara definir a compactação na criação da tabela, afetando leitura e gravação. Usetblpropertiesquando desejar controlar o comportamento de gravação como uma propriedade persistente da tabela.
|
Parâmetro |
Quando adicionar |
Descrição |
Valor |
Padrão |
|
|
Quando os arquivos de dados do OSS usam o formato Raw-Snappy |
Habilita o resolvedor integrado para dados compactados com Raw-Snappy. Quando definido, o MaxCompute consegue ler dados compactados. |
|
Nenhum |
|
|
Para adicionar um prefixo personalizado aos nomes dos arquivos de saída |
Apenas letras, dígitos e sublinhados (a–z, A–Z, 0–9, |
Por exemplo, |
Nenhum |
|
|
Para incluir extensões de arquivo nos nomes de saída |
|
|
|
|
|
Para adicionar um sufixo personalizado aos nomes dos arquivos de saída |
Apenas letras, dígitos e sublinhados. |
Por exemplo, |
Nenhum |
|
|
Para definir uma extensão de arquivo personalizada |
Apenas letras, dígitos e sublinhados. Comprimento: 1–10 caracteres. Tem precedência sobre |
Por exemplo, |
Nenhum |
|
|
Ao gravar dados Parquet no OSS em formato compactado |
Define o codec de compactação. Dados Parquet não são compactados por padrão. |
|
Nenhum |
|
|
Para controlar a eficiência de armazenamento e o desempenho de leitura |
Tamanho do bloco Parquet em bytes. |
Inteiro não negativo |
|
|
|
Para evitar erros de falta de memória (OOM) ao gravar grandes conjuntos de dados |
Número máximo de registros por grupo de linhas. Reduza este valor se ocorrer OOM. Se a memória JVM for de 1 GB e o tamanho médio do registro for de 1 MB, defina como aproximadamente 100 (o tamanho padrão do grupo de linhas é 128 MB). Não defina um valor muito baixo. |
Inteiro não negativo |
|
|
|
Para controlar a frequência de verificação de memória durante gravações |
Mínimo de registros entre verificações de memória. Reduza este valor se ocorrer OOM. |
Inteiro não negativo |
|
|
|
Para controlar a frequência de verificação de memória durante gravações |
Máximo de registros entre verificações de memória. Por padrão, o MaxCompute verifica a memória a cada 10.000 registros. Para registros pequenos, reduza para 1.000 para verificações mais frequentes. Como verificações frequentes adicionam sobrecarga, primeiro reduza |
Inteiro não negativo |
|
|
|
Ao gravar dados Parquet com compactação ZSTD |
Nível de compactação ZSTD. Valores válidos: 1–22. |
Inteiro não negativo |
|
Gravar dados
Para a sintaxe de gravação, consulte Sintaxe de gravação.
Consulta e análise
Para a sintaxe SELECT, consulte Sintaxe de consulta.
Para otimização do plano de consulta, consulte Otimização de consulta.
Para consultar arquivos LOCATION sem definir um schema, consulte Consulta sem schema.
Predicate push down
Por padrão, consultas em tabelas externas Parquet com filtros WHERE varrem todos os dados, independentemente das condições de filtro. O Parquet Predicate Push Down (PPD) usa metadados de grupos de linhas incorporados aos arquivos Parquet para pular grupos que não correspondem ao filtro, reduzindo o volume de dados verificados, a latência da consulta e o uso de recursos.
O PPD exige o modo nativo (odps.ext.parquet.native=true). Ative-o executando estes comandos SET no nível de sessão antes da consulta:
-- Enable Native mode (required for PPD).
SET odps.ext.parquet.native = true;
-- Enable Parquet PPD.
SET odps.sql.parquet.use.predicate.pushdown = true;
Comparação de desempenho
Os resultados a seguir provêm de um benchmark TPCDS de 1 TB usando a tabela tpcds_1t_store_sales (2.879.987.999 linhas no total).
|
Modo |
Linhas verificadas |
Bytes verificados |
Tempo do Mapper |
CPU |
Memória |
|
Tabela externa, PPD desativado |
2.879.987.999 (100%) |
19.386.793.984 (100%) |
18 s |
19,25 Core×Min |
24,07 GB×Min |
|
Tabela externa, PPD ativado |
762.366.649 (26,47%) |
3.339.386.880 (17,22%) |
12 s |
11,47 Core×Min |
14,33 GB×Min (~59,58%) |
|
Tabela interna, PPD ativado |
32.830.000 (1,14%) |
1.633.880.386 (8,43%) |
9 s |
5,62 Core×Min |
7,02 GB×Min (~29,19%) |
A ativação do PPD na tabela externa reduziu os bytes verificados de 100% para 17,22% e diminuiu o uso de recursos em aproximadamente 40%. Tabelas internas apresentam ganhos ainda maiores porque os dados são ordenados, tornando a poda de grupos de linhas mais eficaz.
Mesmo com o PPD ativado, tabelas externas verificam significativamente mais dados do que tabelas internas (17,22% contra 8,43% dos bytes). Se o desempenho da consulta for crítico e os dados mudarem com pouca frequência, considere carregar os dados em uma tabela interna.
Detalhes do teste
-
Tabela externa com PPD desativado
SET odps.ext.parquet.native = true; SET odps.sql.parquet.use.predicate.pushdown = false; SELECT SUM(ss_sold_date_sk) FROM tpcds_1t_store_sales WHERE ss_store_sk = 2 AND ss_sold_date_sk >= 2451871 AND ss_sold_date_sk <= 2451880;


-
Tabela externa com PPD ativado
SET odps.ext.parquet.native = true; SET odps.sql.parquet.use.predicate.pushdown = true; SELECT SUM(ss_sold_date_sk) FROM tpcds_1t_store_sales WHERE ss_store_sk = 2 AND ss_sold_date_sk >= 2451871 AND ss_sold_date_sk <= 2451880;Muitos mappers estão vazios e pulam a leitura de dados: Log real de poda de grupos de linhas:




-
Tabela interna com PPD ativado Os dados da tabela interna são ordenados, portanto a poda é mais eficaz.
SELECT SUM(ss_sold_date_sk) FROM bigdata_public_dataset.tpcds_1t.store_sales WHERE ss_store_sk = 2 AND ss_sold_date_sk >= 2451871 AND ss_sold_date_sk <= 2451880;


Exemplo: crie e use uma tabela externa Parquet compactada com ZSTD
Este exemplo cria uma tabela externa Parquet particionada com compactação ZSTD e, em seguida, lê e grava dados.
Pré-requisitos
Antes de começar, certifique-se de ter:
Um bucket e uma pasta no OSS na mesma região do seu projeto MaxCompute. Consulte Criar um bucket e Gerencie pastas
Permissões de acesso ao OSS por meio de uma conta Alibaba Cloud, um usuário RAM ou uma função RAM. Consulte Autorização STS para OSS
A permissão
CreateTableno seu projeto MaxCompute. Consulte Permissões do MaxCompute
Etapas
Prepare arquivos de dados formatados em ZSTD. No bucket
oss-mc-testdos dados de amostra, crie o diretórioparquet_zstd_jni/dt=20230418e coloque os dados particionados nesse diretório.-
Crie uma tabela externa Parquet compactada com ZSTD.
CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_parquet_data_type_zstd ( vehicleId INT, recordId INT, patientId INT, calls INT, locationLatitute DOUBLE, locationLongtitue DOUBLE, recordTime STRING, direction STRING ) PARTITIONED BY (dt STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' WITH serdeproperties( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole', 'mcfed.parquet.compression'='zstd' ) STORED AS parquet LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/parquet_zstd_jni/'; -
Adicione partições à tabela externa.
MSCK REPAIR TABLE mc_oss_parquet_data_type_zstd ADD PARTITIONS;Para mais opções, consulte Adicionar partições a tabelas externas do OSS.
-
Leia dados da tabela.
SELECT * FROM mc_oss_parquet_data_type_zstd WHERE dt='20230418' LIMIT 10;Saída esperada:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | dt | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | SW | 20230418 | | 1 | 1 | 51 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:00 | S | 20230418 | | 1 | 2 | 13 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:01 | NE | 20230418 | | 1 | 3 | 48 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:02 | NE | 20230418 | | 1 | 4 | 30 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:03 | W | 20230418 | | 1 | 5 | 47 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:04 | S | 20230418 | | 1 | 6 | 9 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:05 | S | 20230418 | | 1 | 7 | 53 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:06 | N | 20230418 | | 1 | 8 | 63 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:07 | SW | 20230418 | | 1 | 9 | 4 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:08 | NE | 20230418 | | 1 | 10 | 31 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:09 | N | 20230418 | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+ -
Grave dados na tabela.
INSERT INTO mc_oss_parquet_data_type_zstd PARTITION (dt = '20230418') VALUES (1,16,76,1,46.81006,-92.08174,'9/14/2014 0:10','SW'); -- Verify the inserted row. SELECT * FROM mc_oss_parquet_data_type_zstd WHERE dt = '20230418' AND recordid=16;Saída esperada:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | dt | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+ | 1 | 16 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | SW | 20230418 | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
Solução de problemas
Incompatibilidade de tipo de coluna
Erro:
ODPS-0123131:User defined function exception - Traceback:
java.lang.ClassCastException: org.apache.hadoop.io.LongWritable cannot be cast to org.apache.hadoop.io.IntWritable
at org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableIntObjectInspector.getPrimitiveJavaObject(WritableIntObjectInspector.java:46)
O arquivo Parquet armazena a coluna como LongWritable (BIGINT), mas o DDL da tabela externa a define como INT. Altere o tipo da coluna no DDL de INT para BIGINT.
Erro de falta de memória durante gravação
Erro:
ODPS-0123131:User defined function exception - Traceback:
java.lang.OutOfMemoryError: Java heap space
at java.io.ByteArrayOutputStream.<init>(ByteArrayOutputStream.java:77)
at org.apache.parquet.bytes.BytesInput$BAOS.<init>(BytesInput.java:175)
at org.apache.parquet.bytes.BytesInput$BAOS.<init>(BytesInput.java:173)
at org.apache.parquet.bytes.BytesInput.toByteArray(BytesInput.java:161)
Esse erro ocorre ao gravar grandes volumes de dados em uma tabela externa Parquet. Resolva-o seguindo esta ordem:
Reduza
mcfed.parquet.block.row.count.limitemtblproperties.Se o OOM persistir ou se os arquivos de saída forem muito grandes, reduza também
mcfed.parquet.page.size.row.check.max.
Adicione estas configurações no nível de sessão antes de gravar:
-- Set maximum JVM heap memory for UDFs.
SET odps.sql.udf.jvm.memory=12288;
-- Control batch size on the runtime side.
SET odps.sql.executionengine.batch.rowcount=64;
-- Set memory size per mapper.
SET odps.stage.mapper.mem=12288;
-- Adjust input data size per mapper (file split size).
SET odps.stage.mapper.split.size=64;