Crie uma tabela externa a partir de arquivos CSV

Big DataBeginner
Pratique Agora

Introdução

No primeiro laboratório de Hive, uma tabela preparada permitiu consultar linhas de pedidos imediatamente. Agora, a empresa varejista forneceu arquivos CSV, mas um arquivo no armazenamento ainda não é uma tabela que o Hive saiba consultar. Você precisa descrever seus campos e identificar o diretório que guarda seus dados.

Uma tabela externa é uma definição de tabela que se refere a dados gerenciados separadamente dessa definição. Seu esquema especifica nomes e tipos de colunas, e seu LOCATION aponta para os arquivos armazenados. Criar a definição não envia os arquivos nem reescreve seu conteúdo. O Hive mantém os metadados da tabela em seu Metastore, enquanto os registros permanecem no armazenamento.

Você enviará duas origens CSV simples, mapeará a primeira com um esquema explícito, mudará o mapeamento para a segunda e excluirá apenas uma definição descartável de tabela externa. O experimento final usa propriedades explícitas de retenção de dados na versão do Hive deste curso; ele não garante que excluir qualquer tabela possível do Hive preserve arquivos. Os serviços e as entradas locais são preparados de forma independente, e não é necessário ter feito o curso de Hadoop nem conhecer uma linguagem de programação. Use o Terminal.

Inspecione e envie os arquivos de origem

Nesta etapa, você inspecionará o formato CSV e copiará os dois arquivos fornecidos para diretórios separados no HDFS.

Comece no projeto local:

cd /home/labex/project

Um arquivo CSV separa campos com vírgulas. Estes arquivos didáticos contêm valores simples sem vírgulas internas, texto entre aspas com várias linhas nem separadores escapados. O formato simples de tabela usado aqui foi escolhido para essas entradas, não como um analisador universal de todos os dialetos CSV.

O comando local head -n 4 exibe as primeiras quatro linhas:

head -n 4 /home/labex/project/data/orders-a.csv

Você deverá ver um cabeçalho seguido de três registros de pedidos:

order_id,customer_id,product_id,quantity,unit_price,order_status,order_date
o1,c1,p1,2,10.00,paid,2026-10-14
o2,c2,p2,1,25.00,paid,2026-10-14
o3,c1,p1,1,10.00,pending,2026-10-14

Conte as linhas terminadas por quebra de linha com wc -l:

wc -l /home/labex/project/data/orders-a.csv /home/labex/project/data/orders-b.csv

A origem A tem sete linhas, mas apenas seis registros de negócio; a origem B tem três linhas, mas apenas dois registros. O cabeçalho não deve se tornar uma linha de pedido.

O HDFS é um sistema de arquivos separado usado pelo serviço Hive preparado. O cliente hdfs dfs gerencia seus arquivos. -mkdir -p cria os diretórios nomeados do HDFS e os diretórios-pai ausentes:

hdfs dfs -mkdir -p /user/labex/hive-mapping/source-a /user/labex/hive-mapping/source-b

A operação -put copia uma origem local para um destino no HDFS, mantendo o original intacto:

hdfs dfs -put /home/labex/project/data/orders-a.csv /user/labex/hive-mapping/source-a/orders.csv

Envie a segunda origem para seu próprio diretório:

hdfs dfs -put /home/labex/project/data/orders-b.csv /user/labex/hive-mapping/source-b/orders.csv

Um envio bem-sucedido normalmente não imprime nada. Um destino já existente deve ser inspecionado antes de qualquer decisão de sobrescrita; não exclua dados brutos apenas para repetir um comando. Leia o primeiro arquivo do HDFS com -cat:

hdfs dfs -cat /user/labex/hive-mapping/source-a/orders.csv

Seu cabeçalho e seus seis registros continuam presentes. O envio preserva bytes; uma definição de tabela informará ao Hive como interpretá-los.

Defina o mapeamento de arquivo para tabela

Nesta etapa, você criará uma tabela externa com campos, tipos, local de diretório e tratamento de cabeçalho explícitos.

A ordem dos campos da origem deve corresponder à ordem das colunas da tabela. Use STRING para identificadores e status, INT para uma quantidade inteira, DECIMAL(10,2) para um preço de ponto fixo e DATE para a data em formato ISO. Preços decimais evitam aproximações de ponto flutuante binário nos cálculos monetários posteriores.

CREATE DATABASE IF NOT EXISTS cria o espaço de nomes se necessário. CREATE EXTERNAL TABLE registra uma definição de tabela. As cláusulas de formato especificam texto separado por vírgulas; LOCATION nomeia o diretório, portanto mantenha arquivos não relacionados e cópias de segurança fora dele. As duas propriedades ignoram uma linha de cabeçalho por arquivo e desativam explicitamente a exclusão dos dados da tabela externa ao executar DROP neste ambiente.

Salve o arquivo SQL completo. Como no primeiro laboratório, o here-document do shell grava linhas literais até o delimitador final SQL:

cat > /home/labex/project/queries/create-orders.sql <<'SQL'
CREATE DATABASE IF NOT EXISTS retail_mapping;
USE retail_mapping;
CREATE EXTERNAL TABLE raw_orders (
  order_id STRING,
  customer_id STRING,
  product_id STRING,
  quantity INT,
  unit_price DECIMAL(10,2),
  order_status STRING,
  order_date DATE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION 'hdfs://localhost:9000/user/labex/hive-mapping/source-a'
TBLPROPERTIES ('skip.header.line.count'='1', 'external.table.purge'='false');
SQL

Execute-o com Beeline. A conexão e a opção de arquivo -f são as mesmas do primeiro laboratório:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true -f /home/labex/project/queries/create-orders.sql

Estas são instruções DDL (Data Definition Language, linguagem de definição de dados): instruções SQL que definem objetos, como tabelas. Instruções DDL bem-sucedidas criam metadados, em vez de retornar linhas de pedidos. Se a tabela já existir devido a uma execução concluída, inspecione-a em vez de excluí-la para silenciar a mensagem.

DESCRIBE FORMATTED inclui o tipo e o local da tabela, além de suas colunas:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'DESCRIBE FORMATTED retail_mapping.raw_orders;'

Localize EXTERNAL_TABLE e o local terminando em /hive-mapping/source-a. Essas são observações de metadados, não evidências de que todos os registros foram interpretados corretamente. Use também uma consulta. COUNT(*) conta as linhas da tabela, portanto oferece uma conferência rápida do mapeamento. AS order_count dá a esse resultado calculado um nome de coluna, chamado alias; ele não renomeia um campo de origem nem altera os registros armazenados:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SELECT COUNT(*) AS order_count FROM retail_mapping.raw_orders; SELECT order_id, quantity, unit_price, order_date FROM retail_mapping.raw_orders ORDER BY order_id LIMIT 2;'

A contagem deverá ser 6, não as sete linhas de texto do arquivo. Os primeiros dois registros deverão conter os IDs o1, o2, quantidades 2, 1, preços numericamente iguais a 10.00, 25.00 e data 2026-10-14. Você verificou tanto o tratamento do cabeçalho quanto colunas tipadas com significado.

Aponte a mesma tabela para uma nova origem

Nesta etapa, você mudará o local da tabela e preverá como isso altera suas linhas sem mover nenhum dos arquivos de origem.

A origem B tem os mesmos campos, mas contém os pedidos o7 e o8. Leia o arquivo armazenado antes de alterar os metadados:

hdfs dfs -cat /user/labex/hive-mapping/source-b/orders.csv

Você deverá ver seu cabeçalho e dois registros. Preveja a contagem de linhas da tabela após apontá-la para este diretório: duas, em vez de seis. ALTER TABLE ... SET LOCATION altera a referência ao diretório na definição da tabela. Ele não copia os dados antigos para o novo diretório nem combina os dois recebimentos.

Salve essa alteração de metadados:

cat > /home/labex/project/queries/map-second-source.sql <<'SQL'
ALTER TABLE retail_mapping.raw_orders SET LOCATION 'hdfs://localhost:9000/user/labex/hive-mapping/source-b';
SQL

Execute-a:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true -f /home/labex/project/queries/map-second-source.sql

Inspecione novamente tanto os metadados quanto os dados:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'DESCRIBE FORMATTED retail_mapping.raw_orders; SELECT COUNT(*) AS order_count FROM retail_mapping.raw_orders; SELECT order_id, quantity, unit_price FROM retail_mapping.raw_orders ORDER BY order_id;'

Localize o novo local source-b, a contagem 2 e as linhas de o7 e o8. Suas quantidades são 1 e 2, e seus preços são numericamente 50.00 e 15.00. As definições de coluna não mudaram; apenas os arquivos lidos por meio delas mudaram.

Leia o arquivo antigo para conferir que alterar o mapeamento não o removeu:

hdfs dfs -cat /user/labex/hive-mapping/source-a/orders.csv

Seus seis registros e o cabeçalho ainda deverão estar presentes. Existência de arquivo e visibilidade pela tabela são fatos diferentes: a origem A continua existindo, embora esta tabela agora leia a origem B.

Exclua apenas uma definição de tabela descartável

Nesta etapa, você criará e removerá uma definição de tabela externa sobre a primeira origem retida, mantendo os dados e a tabela principal.

Excluir uma definição de tabela e excluir seus dados são operações diferentes. Para este experimento, use um nome separado, disposable_orders, com as propriedades explícitas de retenção de dados externos. Mantenha raw_orders, que agora mapeia a origem B, disponível durante todo o processo.

Crie a definição descartável sobre a origem A usando o mesmo esquema conhecido:

cat > /home/labex/project/queries/create-disposable.sql <<'SQL'
CREATE EXTERNAL TABLE retail_mapping.disposable_orders (
  order_id STRING,
  customer_id STRING,
  product_id STRING,
  quantity INT,
  unit_price DECIMAL(10,2),
  order_status STRING,
  order_date DATE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION 'hdfs://localhost:9000/user/labex/hive-mapping/source-a'
TBLPROPERTIES ('skip.header.line.count'='1', 'external.table.purge'='false');
SQL

Execute a definição:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true -f /home/labex/project/queries/create-disposable.sql

Confira se os dois nomes de tabela existem:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SHOW TABLES IN retail_mapping;'

Você deverá ver disposable_orders e raw_orders. DROP TABLE remove uma definição de tabela. Aqui, ele tem como alvo apenas a tabela externa descartável, cuja propriedade de exclusão de dados está explicitamente definida como false:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'DROP TABLE retail_mapping.disposable_orders; SHOW TABLES IN retail_mapping;'

Apenas raw_orders deverá permanecer. Agora inspecione o arquivo de origem de forma independente:

hdfs dfs -cat /user/labex/hive-mapping/source-a/orders.csv

O cabeçalho e os seis registros deverão permanecer. Esse comportamento observado se aplica a esta configuração de tabela externa. Uma tabela gerenciada ou uma tabela externa com propriedades diferentes de exclusão pode remover dados ao ser excluída; não generalize este experimento como uma regra universal de exclusão.

Confirme que a tabela principal ainda lê a origem B:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SELECT order_id FROM retail_mapping.raw_orders ORDER BY order_id;'

Você ainda deverá ver o7 e o8. Você separou três operações que iniciantes costumam confundir: enviar bytes, registrar ou alterar metadados e remover uma definição. A seguir, usará essas linhas corretamente mapeadas para filtrar condições e lidar com valores ausentes.

Resumo

Você enviou origens CSV simples, declarou a ordem e os tipos de seus campos, ignorou cabeçalhos e registrou uma tabela externa em um diretório explícito do HDFS. Conferiu tanto os metadados quanto os registros reais e mudou o local da tabela sem mover nenhum dos arquivos de origem.

Por fim, removeu uma definição descartável de tabela externa sob configurações explícitas de retenção e confirmou que os arquivos e a tabela principal continuavam disponíveis. A seguir, usará um mapeamento confiável como base para escolher linhas e lidar com valores ausentes.