소개
터미널에 표시한 쿼리는 한 번 확인하는 데 유용합니다. 다른 쿼리에서 재사용할 보고서에는 저장된 결과가 필요합니다. 소매업체의 일일 결제 완료 판매 쿼리를 작은 Hive 테이블로 바꾸고 같은 보고서를 다시 요청할 때 안전하게 다시 만듭니다.
원본은 읽을 수 있는 CSV 텍스트입니다. **ORC(Optimized Row Columnar)**는 이진 열 기반 저장 형식입니다. 파일 구조 안에서 값을 열별로 구성하며 효율적인 분석 읽기를 지원할 수 있습니다. 또 다른 SQL 언어나 테이블 스키마를 대체하는 것은 아닙니다. 이 작은 예제는 속도 향상을 증명하기보다 올바른 저장과 재사용을 보여줍니다.
이번 실습은 정상 주문 여섯 건을 외부 텍스트 테이블에 독립적으로 준비합니다. Hive도 준비되어 있습니다. 외부 테이블, SELECT, 결제 완료 판매 집계와 날짜 그룹화를 이해하면 됩니다. 준비된 환경이 지원하는 명시적 비트랜잭션 테이블로 결과 쓰기 문장을 여기서 배웁니다. 프로그래밍, 설치나 이전 실습 파일은 필요하지 않습니다. 터미널을 사용하세요.
자료형이 있는 ORC 보고서 테이블 정의하기
이 단계에서는 의도한 보고서에 맞는 스키마를 가진 빈 대상을 만듭니다. CSV 원본처럼 대상도 알려진 HDFS 위치의 명시적인 외부 테이블입니다. 형식은 텍스트 대신 ORC입니다. 외부라는 말은 메타데이터와 파일의 관계를 설명하며 읽기 전용을 뜻하지 않습니다. Hive는 여기에 SELECT 결과를 쓸 수 있습니다. 결과 위치를 원본과 분리하므로 보고서를 다시 만들어도 원래 주문을 바꾸지 않습니다.
작업 공간에서 시작합니다.
cd /home/labex/project
출력의 각 행에는 날짜 하나, 개수 하나와 금액 합계 하나가 있습니다. COUNT(*)는 BIGINT 개수를 만듭니다. DECIMAL(14,2)는 전체 십진수 열네 자리 중 소수점 아래 두 자리를 사용하며 작은 보고서에 충분합니다. 명시적 스키마는 실수로 금액을 텍스트로 저장하는 일을 방지하는 데 도움이 됩니다.
정의를 저장하고 실행합니다. 히어 도큐먼트는 표시 사이의 SQL을 그대로 쓰고 Beeline의 -f는 준비된 서비스에 그 파일을 실행합니다.
cat > /home/labex/project/queries/create-orc-report.sql <<'SQL'
CREATE EXTERNAL TABLE IF NOT EXISTS retail_orc.daily_sales (
order_date DATE,
paid_orders BIGINT,
revenue DECIMAL(14,2)
)
STORED AS ORC
LOCATION 'hdfs://localhost:9000/warehouse/external/retail_orc.db/daily_sales'
TBLPROPERTIES ('transactional'='false', 'external.table.purge'='false');
SQL
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/create-orc-report.sql
STORED AS ORC는 형식을 선택합니다. LOCATION은 준비된 데이터베이스의 쓰기 가능한 웨어하우스 디렉터리 아래에 새 결과 디렉터리를 지정합니다. external.table.purge=false는 외부 정의를 삭제할 때 파일을 유지하며, 명시적 덮어쓰기가 보고서 행을 바꾸는 것을 막지는 않습니다. transactional=false는 비트랜잭션 테이블을 요청합니다. Hive는 표시 메타데이터에서 이 false 속성을 생략할 수 있습니다. true 값일 때만 트랜잭션 테이블을 뜻합니다. 이 실습은 ACID 갱신이나 삭제를 다루지 않습니다. 메타데이터와 빈 행 수를 확인합니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "DESCRIBE FORMATTED retail_orc.daily_sales;" > /home/labex/project/output/orc-definition.txt
cat /home/labex/project/output/orc-definition.txt
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT COUNT(*) FROM retail_orc.daily_sales;" > /home/labex/project/output/empty-report.tsv
cat /home/labex/project/output/empty-report.tsv
세 열의 자료형, 외부 테이블 유형과 ORC 입력 및 출력 형식 이름을 찾으세요. 행 수는 0입니다. 대상을 정의해도 판매 계산을 실행하거나 CSV 데이터를 복사하지는 않았습니다. 다음으로 명시적으로 데이터를 채웁니다.
일일 보고서를 쓰고 다시 읽기
이 단계에서는 결제 완료 판매 SELECT를 실행하고 출력을 저장합니다. INSERT OVERWRITE TABLE은 대상 테이블의 현재 내용을 SELECT 결과로 바꿉니다. 읽는 외부 orders 테이블을 덮어쓰지는 않습니다. 선택한 값은 날짜, 개수, 매출 순서대로 대상 열에 할당됩니다.
전체 재생성 스크립트를 저장합니다. CREATE TABLE IF NOT EXISTS는 올바르게 정의된 테이블이 이미 있을 때 정의를 다시 실행할 수 있게 하지만 잘못된 스키마를 고치지는 않습니다. 이어지는 INSERT가 실제로 보고서를 만듭니다.
cat > /home/labex/project/queries/build-sales-report.sql <<'SQL'
CREATE EXTERNAL TABLE IF NOT EXISTS retail_orc.daily_sales (
order_date DATE,
paid_orders BIGINT,
revenue DECIMAL(14,2)
)
STORED AS ORC
LOCATION 'hdfs://localhost:9000/warehouse/external/retail_orc.db/daily_sales'
TBLPROPERTIES ('transactional'='false', 'external.table.purge'='false');
INSERT OVERWRITE TABLE retail_orc.daily_sales
SELECT order_date, COUNT(*) AS paid_orders,
SUM(quantity * unit_price) AS revenue
FROM retail_orc.orders
WHERE order_status = 'paid'
GROUP BY order_date;
SQL
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/build-sales-report.sql
성공적인 완료는 쓰기가 끝났다는 뜻입니다. 원래의 원본 SELECT를 다시 실행하는 데 그치지 말고 저장된 ORC 테이블을 조회하여 확인합니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales ORDER BY order_date;" > /home/labex/project/output/stored-report.tsv
cat /home/labex/project/output/stored-report.tsv
10월 14일 / 2 / 45.00과 10월 15일 / 2 / 80.00이 예상됩니다. 금액 표시에 뒤따르는 0이 있을 수 있습니다. 이들은 원본 결제 완료 주문 네 건을 요약하는 저장 결과 두 행이며 원래 CSV 기록 여섯 개의 복사본이 아닙니다.
ORC 파일은 이진 형식이므로 cat으로 바이트를 보아도 읽을 수 있는 CSV가 나오지 않습니다. Hive는 SELECT할 때 테이블 스키마와 파일 형식을 해석합니다. 원본 파일은 일반 텍스트로 남으며 제외한 두 상태를 포함해 주문 여섯 건 모두를 유지합니다.
날짜가 중복 누적되지 않게 다시 만들기
이 단계에서는 반복 가능성을 테스트합니다. 같은 덮어쓰기 스크립트를 다시 실행하면 행 수가 어떻게 될지 예상해 보세요. 대상에는 복사된 요약 네 행이 아니라 여전히 날짜 두 개가 있어야 합니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/build-sales-report.sql
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales ORDER BY order_date;" > /home/labex/project/output/rebuilt-report.tsv
cat /home/labex/project/output/rebuilt-report.tsv
보고서는 여전히 10월 14일 / 2 / 45.00과 10월 15일 / 2 / 80.00이어야 합니다. 결과 테이블에서 직접 간단히 합계를 맞춰 봅니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT COUNT(*), SUM(paid_orders), SUM(revenue) FROM retail_orc.daily_sales;" > /home/labex/project/output/report-reconciliation.tsv
cat /home/labex/project/output/report-reconciliation.tsv
저장된 보고서 2행, 원본 결제 완료 주문 4건, 매출 125.00이 예상됩니다. 결과의 행 수와 paid_orders 합계는 서로 다른 상세 수준을 설명합니다.
저장한 전후 데이터를 로컬에서 비교하세요. 두 SELECT 문 모두 ORDER BY를 사용하므로 데이터 행 순서는 안정적입니다. Beeline에는 클라이언트 메시지가 포함될 수 있으므로 메시지 타임스탬프보다 날짜별 결과 행과 숫자 합계를 비교하는 것이 의미 있습니다.
이 재생성은 입력이 같을 때 멱등적입니다. 반복해도 보고서 내용이 같습니다. 다음에는 일회용 대상으로 쓰기 모드가 중요한 이유를 살펴봅니다.
일회용 사본에서 추가 쓰기와 덮어쓰기 비교하기
이 단계에서는 별도 테이블에 작은 파생 보고서를 의도적으로 중복 저장합니다. 주 daily_sales 테이블은 올바른 보고서로 유지됩니다. 같은 명시적 스키마로 일회용 테이블을 만듭니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "CREATE EXTERNAL TABLE IF NOT EXISTS retail_orc.append_demo (
order_date DATE,
paid_orders BIGINT,
revenue DECIMAL(14,2)
)
STORED AS ORC
LOCATION 'hdfs://localhost:9000/warehouse/external/retail_orc.db/append_demo'
TBLPROPERTIES ('transactional'='false', 'external.table.purge'='false');"
INSERT INTO TABLE은 SELECT 결과를 기존 내용 뒤에 추가합니다. 두 행의 주 보고서를 두 번 추가합니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "INSERT INTO TABLE retail_orc.append_demo SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales;"
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "INSERT INTO TABLE retail_orc.append_demo SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales;"
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT COUNT(*), SUM(paid_orders), SUM(revenue) FROM retail_orc.append_demo;" > /home/labex/project/output/append-observation.tsv
cat /home/labex/project/output/append-observation.tsv
4행, 합산된 결제 완료 주문 8건, 매출 250.00이 예상됩니다. 추가 행은 새로운 판매가 아니라 중복 보고서 사본입니다. 새 주문이 도착하지 않았는데 전체 재생성 결과를 추가해서 잘못된 업무 결과를 만들었습니다.
앞서 배운 쓰기 모드로 일회용 내용을 사본 하나로 바꿉니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "INSERT OVERWRITE TABLE retail_orc.append_demo SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales;"
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT order_date, paid_orders, revenue FROM retail_orc.append_demo ORDER BY order_date;" > /home/labex/project/output/overwrite-observation.tsv
cat /home/labex/project/output/overwrite-observation.tsv
올바른 날짜별 두 행으로 돌아옵니다. 작은 연습으로 덮어쓰기를 한 번 더 반복합니다.
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "INSERT OVERWRITE TABLE retail_orc.append_demo SELECT order_date, paid_orders, revenue FROM retail_orc.daily_sales;"
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e "SELECT COUNT(*), SUM(revenue) FROM retail_orc.append_demo;"
다시 2행과 125.00이 예상됩니다. 추가 쓰기는 실제로 새롭고 겹치지 않는 데이터를 더할 때 유용합니다. 전체 스냅샷 재생성에는 교체 의미가 필요합니다. 저장한 주 생성 스크립트는 덮어쓰기를 사용하므로 날짜 중복을 조용히 누적하지 않고 전체 보고서를 다시 만들 수 있습니다.
요약
자료형이 있는 비트랜잭션 ORC 결과 테이블을 정의하고 일일 결제 완료 판매 합계를 쓴 뒤 다시 읽고 반복 가능한 재생성을 테스트했습니다. 일회용 추가 쓰기 실험으로 중복 보고서 사본이 매출을 부풀리는 과정과 덮어쓰기가 전체 스냅샷을 복원하는 방식을 확인했습니다. 다음에는 마지막 보고 도전 과제 전에 일반적인 파일과 테이블 연결 오류를 진단합니다.



