docker network create mynetwork
docker run --name psql --network mynetwork -e POSTGRES_USER=hive -e POSTGRES_PASSWORD=hive -e POSTGRES_DB=hive_metastore -p 5432:5432 -d postgres:14
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value>
</property>
<property>
<name>hive.tez.exec.inplace.progress</name>
<value>false</value>
</property>
<property>
<name>hive.exec.scratchdir</name>
<value>/opt/hive/scratch_dir</value>
</property>
<property>
<name>hive.user.install.directory</name>
<value>/opt/hive/install_dir</value>
</property>
<property>
<name>tez.runtime.optimize.local.fetch</name>
<value>true</value>
</property>
<property>
<name>hive.exec.submit.local.task.via.child</name>
<value>false</value>
</property>
<property>
<name>mapreduce.framework.name</name>
<value>local</value>
</property>
<property>
<name>tez.local.mode</name>
<value>true</value>
</property>
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
<property>
<name>metastore.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://hms:9083</value>
<description>URI for the Hive Metastore server</description>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:postgresql://psql:5432/hive_metastore</value>
<description>JDBC connection URL for the Hive Metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>org.postgresql.Driver</value>
<description>JDBC Driver for PostgreSQL</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
<description>JDBC username for PostgreSQL</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>hive</value>
<description>JDBC password for PostgreSQL</description>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>file:/opt/hive/warehouse</value>
</property>
</configuration>
wget https://jdbc.postgresql.org/download/postgresql-42.2.5.jar
ls ./jars/pos*
./jars/postgresql-42.2.5.jar
docker run -d -p 9083:9083 \
--env SERVICE_NAME=metastore \
--env DB_DRIVER=postgres \
--name hms \
-v ./jars/postgresql-42.2.5.jar:/opt/hive/lib/postgresql-42.2.5.jar \
-v ./hms/hive-site.xml:/opt/hive/conf/hive-site.xml \
-v ./hms/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml \
--network mynetwork apache/hive:4.0.1
docker run -d -p 10000:10000 -p 10002:10002 --env SERVICE_NAME=hiveserver2 \
--env DB_DRIVER=postgres \
--env SERVICE_OPTS="-Dhive.metastore.uris=thrift://hms:9083" \
--env IS_RESUME="true" \
-v ./hms/hive-site.xml:/opt/hive/conf/hive-site.xml \
-v ./hms/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml \
--network mynetwork \
--name hs2 apache/hive:4.0.1
컨테이너가 실행할 Hive 서비스의 종류를 지정한다. /opt/hive/bin/startup.sh 또는 /docker-entrypoint.sh (이미지 내부 스크립트)에서 사용하는 값이다.
즉, 이 값에 따라 컨테이너가 실행할 서비스 프로세스가 달라진다.
Hive Metastore가 사용할 데이터베이스 드라이버 종류를 지정한다.엔트리포인트 스크립트(startup.sh) 내부에서 JDBC URL을 구성할 때 사용된다. Hive Metastore는 내부적으로 RDBMS(MySQL, Postgres 등)에 메타데이터를 저장하므로, DB_DRIVER 값을 통해 어떤 드라이버를 쓸지 결정한다.
| DB_DRIVER 값 | 의미 | 기본 JDBC URL 예시 |
|---|---|---|
derby | 내장 Derby DB (기본값) | jdbc:derby:;databaseName=metastore_db;create=true |
mysql | MySQL | jdbc:mysql://mysql:3306/hive_metastore?createDatabaseIfNotExist=true |
postgres | PostgreSQL | jdbc:postgresql://postgres:5432/hive_metastore |
docker exec -it hs2 beeline -u "jdbc:hive2://hs2:10000/default" -n hive
- 테이블 생성
``` bash
0: jdbc:hive2://localhost:10000/default> CREATE TABLE hello_hive (id INT, msg STRING);
0: jdbc:hive2://localhost:10000/default> INSERT INTO hello_hive VALUES (1, 'hello world'), (2, 'from hive');
0: jdbc:hive2://localhost:10000/default> SELECT * FROM hello_hive;
INFO : OK
INFO : Concurrency mode is disabled, not creating a lock manager
+----------------+-----------------+
| hello_hive.id | hello_hive.msg |
+----------------+-----------------+
| 1 | hello world |
| 2 | from hive |
+----------------+-----------------+
2 rows selected (0.18 seconds)
0: jdbc:hive2://hs2:10000/default> SHOW TABLES IN default LIKE '%hello%';
+-------------+
| tab_name |
+-------------+
| hello_hive |
+-------------+
1 row selected (0.029 seconds)
0: jdbc:hive2://localhost:10000/default> DESCRIBE FORMATTED hello_hive;
+-------------------------------+----------------------------------------------------+----------------------------------------------------+
| col_name | data_type | comment |
+-------------------------------+----------------------------------------------------+----------------------------------------------------+
| # col_name | data_type | comment |
| id | int | |
| msg | string | |
| | NULL | NULL |
| # Detailed Table Information | NULL | NULL |
| Database: | default | NULL |
| OwnerType: | USER | NULL |
| Owner: | hive | NULL |
| CreateTime: | Wed Oct 08 06:16:29 UTC 2025 | NULL |
| LastAccessTime: | UNKNOWN | NULL |
| Retention: | 0 | NULL |
| Location: | file:/opt/hive/data/warehouse/hello_hive | NULL |
+-------------------------------+----------------------------------------------------+----------------------------------------------------+
32 rows selected (0.07 seconds)
hive@462b27557fd5:/opt/hive/data/warehouse$ ls -l /opt/hive/data/warehouse/hello_hive
total 4
-rw-r--r-- 1 hive hive 26 Oct 8 06:16 000000_0
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e6629be78bb apache/hive:4.0.1 "sh -c /entrypoint.sh" 10 minutes ago Up 10 minutes 0.0.0.0:10000->10000/tcp, [::]:10000->10000/tcp, 9083/tcp, 0.0.0.0:10002->10002/tcp, [::]:10002->10002/tcp hs2
b53ae082c851 apache/hive:4.0.1 "sh -c /entrypoint.sh" 23 minutes ago Up 23 minutes 10000/tcp, 0.0.0.0:9083->9083/tcp, [::]:9083->9083/tcp, 10002/tcp hms
c8adb627a25e postgres:14 "docker-entrypoint.s…" 34 minutes ago Up 34 minutes 0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp psql
docker inspect psql | grep -i env -A 10
"Env": [
"POSTGRES_PASSWORD=hive",
"POSTGRES_DB=hive_metastore",
"POSTGRES_USER=hive",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/14/bin",
"GOSU_VERSION=1.18",
"LANG=en_US.utf8",
"PG_MAJOR=14",
"PG_VERSION=14.19-1.pgdg13+1",
"PGDATA=/var/lib/postgresql/data"
],
docker exec -it psql psql -U hive -d hive_metastore
hive_metastore=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+-------+----------+------------+------------+-------------------
hive_metastore | hive | UTF8 | en_US.utf8 | en_US.utf8 |
postgres | hive | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | hive | UTF8 | en_US.utf8 | en_US.utf8 | =c/hive +
| | | | | hive=CTc/hive
template1 | hive | UTF8 | en_US.utf8 | en_US.utf8 | =c/hive +
| | | | | hive=CTc/hive
(4 rows)
hive_metastore=# \c hive_metastore
You are now connected to database "hive_metastore" as user "hive".
hive_metastore=# \dt
hive_metastore=# SELECT * FROM public."TBLS";
TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER | OWNER_TYPE | RETENTION | SD_ID | TBL_NAME | TBL_TYPE | VIEW_EXPANDED_TEXT | VIEW_ORIGINAL_TEXT | IS_REWRITE_ENABLED | WRITE_ID
--------+-------------+-------+------------------+-------+------------+-----------+-------+------------+----------------+--------------------+--------------------+--------------------+----------
1 | 1759991284 | 1 | 0 | hive | USER | 0 | 1 | hello_hive | EXTERNAL_TABLE | | | f | 0
(1 row)
hive_metastore=# SELECT grantee, table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
AND table_name = 'TBLS'
AND grantee = 'hive';
grantee | table_schema | table_name | privilege_type
---------+--------------+------------+----------------
hive | public | TBLS | INSERT
hive | public | TBLS | SELECT
hive | public | TBLS | UPDATE
hive | public | TBLS | DELETE
hive | public | TBLS | TRUNCATE
hive | public | TBLS | REFERENCES
hive | public | TBLS | TRIGGER
(7 rows)
hive_metastore=# SELECT current_user;
hive
| 테이블명 | 설명 |
|---|---|
| DBS | Hive 데이터베이스(스키마) 정보 |
| TBLS | 테이블 정보 |
| SDS | 테이블/파티션의 저장 위치(StorageDescriptor) 정보 |
| COLUMNS_V2 | 컬럼 정의 정보 |
| PARTITION_KEYS | 파티션 키 정보 |
| PARTITIONS | 파티션 메타데이터 |
| SERDES | SerDe (Serialization/Deserialization) 설정 정보 |
| TABLE_PARAMS, PARTITION_PARAMS, DATABASE_PARAMS | key-value 속성 정보 |
# 전체 데이터베이스 목록 조회
SELECT "NAME" AS db_name, "DESC" AS description, "DB_LOCATION_URI"
FROM "DBS";
# 특정 데이터베이스에 속한 테이블 목록 조회
SELECT t."TBL_ID", t."TBL_NAME", d."NAME" AS db_name
FROM "TBLS" t
JOIN "DBS" d ON t."DB_ID" = d."DB_ID"
WHERE d."NAME" = 'default';
# 테이블 상세정보 (저장 위치 포함)
SELECT t."TBL_NAME", d."NAME" AS db_name, s."LOCATION", s."INPUT_FORMAT", s."OUTPUT_FORMAT"
FROM "TBLS" t
JOIN "DBS" d ON t."DB_ID" = d."DB_ID"
JOIN "SDS" s ON t."SD_ID" = s."SD_ID"
WHERE d."NAME" = 'default' AND t."TBL_NAME" = 'hello_hive';
# 테이블의 컬럼 목록
SELECT c."COLUMN_NAME", c."TYPE_NAME", c."COMMENT"
FROM "TBLS" t
JOIN "SDS" s ON t."SD_ID" = s."SD_ID"
JOIN "COLUMNS_V2" c ON s."CD_ID" = c."CD_ID"
WHERE t."TBL_NAME" = 'hello_hive';
# 파티션 키 정보
SELECT p."PKEY_NAME", p."PKEY_TYPE"
FROM "TBLS" t
JOIN "PARTITION_KEYS" p ON t."TBL_ID" = p."TBL_ID"
WHERE t."TBL_NAME" = 'hello_hive';
# 실제 등록된 파티션 목록
SELECT pa."PART_NAME", pa."CREATE_TIME"
FROM "TBLS" t
JOIN "PARTITIONS" pa ON t."TBL_ID" = pa."TBL_ID"
WHERE t."TBL_NAME" = 'hello_hive';
# 테이블 속성 (TBLPROPERTIES)
SELECT "PARAM_KEY", "PARAM_VALUE"
FROM "TABLE_PARAMS"
WHERE "TBL_ID" = (
SELECT "TBL_ID" FROM "TBLS" WHERE "TBL_NAME" = 'hello_hive'
);
# 특정 테이블의 파일 경로만 조회
SELECT s."LOCATION"
FROM "TBLS" t
JOIN "SDS" s ON t."SD_ID" = s."SD_ID"
WHERE t."TBL_NAME" = 'hello_hive';
| 구분 | HiveQL | 일반 SQL (예: PostgreSQL, MySQL) |
|---|---|---|
| 데이터 저장 위치 | HDFS, S3, MinIO 등의 파일시스템 | RDBMS 내부의 테이블 스토리지 엔진 |
| 처리 엔진 | MapReduce / Tez / Spark (분산 배치 처리) | 단일 프로세스 내 실행 (OLTP) |
| 데이터 스키마 | 스키마 온 리드 (Schema-on-Read) | 스키마 온 라이트 (Schema-on-Write) |
| 트랜잭션 | 제한적 (ACID 테이블에서만 지원, Iceberg/HiveTxn) | 완전한 ACID 트랜잭션 지원 |
| 인덱스, 조인 최적화 | 옵티마이저가 분산 단위로 최적화 | RDB 엔진 수준에서 고도화된 인덱스/조인 최적화 |
| 실행 단위 | 파일 단위의 batch task | row-level 처리 |
| 성능 지향점 | 대규모 데이터 처리 (OLAP) | 실시간 질의 처리 (OLTP) |
| 항목 | HiveQL | 일반 SQL |
|---|---|---|
| 실행 방식 | 쿼리를 MapReduce/Tez/Spark Job으로 변환하여 실행 | SQL 엔진이 바로 실행 (in-memory or disk-based) |
| 결과 반영 속도 | 수 초 ~ 수 분 단위 (Batch) | 밀리초 ~ 초 단위 (Interactive) |
| 실행 대상 | Parquet, ORC, Avro, CSV, Iceberg 등 파일 | Table row/column in database |
| 실행 계획 | EXPLAIN 시 MR stages / Spark DAG로 표현 | Query Plan (Seq Scan, Hash Join 등) |
| 항목 | HiveQL | 일반 SQL |
|---|---|---|
| Primary Key / Foreign Key | 개념만 존재, 제약 enforced 안 함 | 실제 referential integrity 유지 |
| Index | 제한적 (거의 사용 안 함) | 중요 성능 요소 |
| View | 지원하지만 실제 물리 실행 시 전체 스캔 | 즉시 실행 또는 옵티마이즈드 실행 |
| Partitioning | 파일 단위 파티션 (dt=20251009) | Range/Hash Partition (row 단위) |
| Bucket | 파일 내 데이터 분할 | 일반 SQL엔 거의 없음 |
| 목적 | HiveQL | 일반 SQL |
|---|---|---|
| 테이블 생성 | CREATE EXTERNAL TABLE sales (id INT, amount DOUBLE) STORED AS PARQUET LOCATION 's3a://bucket/sales/'; | CREATE TABLE sales (id INT, amount DOUBLE); |
| 데이터 삽입 | INSERT INTO sales VALUES (1, 200.5); (MapReduce Job 실행됨) | INSERT INTO sales VALUES (1, 200.5); (즉시 반영) |
| 데이터 위치 확인 | DESCRIBE FORMATTED sales; | 없음 |
| 파티션 관리 | ALTER TABLE sales ADD PARTITION (dt='2025-10-09'); | ALTER TABLE ... PARTITION BY RANGE ... |
Hive는 분산 파일을 다루기 위해 파일 기반의 DDL / 확장형 함수 / 파티션 개념을 갖는다.
CREATE EXTERNAL TABLE logs (
id BIGINT, msg STRING
)
PARTITIONED BY (dt STRING)
STORED AS PARQUET
LOCATION 's3a://minio/logs/';
일반 SQL에는 없는 개념.
외부 경로(HDFS/S3)의 데이터를 "테이블처럼" 읽는 역할.
SET hive.exec.dynamic.partition.mode=nonstrict;
INSERT INTO logs PARTITION (dt)
SELECT id, msg, dt FROM staging_logs;
STORED AS ORC;
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde';
일반 SQL엔 없는 데이터 파싱 개념.
TBLPROPERTIES ('orc.compress'='SNAPPY');
SELECT TRANSFORM (line)
USING 'python my_script.py'
AS (word, count)
FROM text_table;
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenode:9000</value>
</property>
최종 warehouse 경로는 hdfs://namenode:9000/user/hive/warehouse 이다. 즉, fs.defaultFS 가 실제 스킴을 붙여준다.
<property>
<name>hive.metastore.warehouse.dir</name>
<value>s3a://warehouse/iceberg</value>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenode:9000</value>
</property>
warehouse는 s3a://warehouse/iceberg 에 고정된다. 이때는 fs.defaultFS 무시된다 (스킴이 이미 있으므로).
즉, 스킴이 명시되어 있으면 fs.defaultFS는 개입하지 않는다.
docker exec -it hs2 hadoop fs -ls hdfs://namenode:9000/
Found 1 items
drwxr-xr-x - hive hive 0 2025-10-10 07:28 hdfs://namenode:9000/hive