구분자가 단순하고 따옴표가 없으면 ROW FORMAT DELIMITED 로 충분하다. 가장 가볍고 빠르다.
CREATE EXTERNAL TABLE nation (
n_nationkey INT,
n_name STRING,
n_regionkey INT,
n_comment STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/tpch/csv/nation'
TBLPROPERTIES ('skip.header.line.count' = '1');
LOCATION 은 디렉터리를 가리킨다. 파일 하나를 지정하는 것이 아니라 그 디렉터리 안의 파일을 모두 읽는다. skip.header.line.count 는 파일마다 앞에서 지정한 줄 수를 건너뛴다.
OpenCSVSerde 를 쓴다. 따옴표로 감싼 필드와 그 안의 쉼표를 제대로 처리한다.
CREATE EXTERNAL TABLE orders_csv (
o_orderkey STRING,
o_custkey STRING,
o_orderstatus STRING,
o_totalprice STRING,
o_orderdate STRING,
o_comment STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar' = ',',
'quoteChar' = '"',
'escapeChar' = '\\'
)
STORED AS TEXTFILE
LOCATION '/staging/orders'
TBLPROPERTIES ('skip.header.line.count' = '1');
OpenCSVSerde 는 모든 컬럼을 STRING 으로 읽는다. 숫자나 날짜로 선언해도 무시되거나 오류가 난다. 타입이 필요하면 조회 시 캐스팅하거나, 한 번 읽어 Parquet/ORC 테이블로 다시 쓴다.
CREATE TABLE orders STORED AS PARQUET AS
SELECT
CAST(o_orderkey AS BIGINT) AS o_orderkey,
CAST(o_custkey AS BIGINT) AS o_custkey,
o_orderstatus,
CAST(o_totalprice AS DECIMAL(12,2)) AS o_totalprice,
CAST(o_orderdate AS DATE) AS o_orderdate,
o_comment
FROM orders_csv;
CREATE EXTERNAL TABLE tsv_table (
col1 STRING,
col2 STRING,
col3 STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
LOCATION '/user/hadoop/data/';
LOCATION 에 지정한 디렉터리가 없으면 Hive 가 만들어 주기도 하지만, 권한 때문에 실패하는 경우가 많으므로 미리 만들고 소유자를 맞춘다.
hdfs dfs -mkdir -p /staging/orders
hdfs dfs -chown -R hive:hive /staging/orders
hdfs dfs -put local_orders.csv /staging/orders/
EXTERNAL 테이블은 DROP TABLE 해도 데이터 파일이 남는다. 메타데이터만 지운다. 관리형 테이블은 데이터까지 지우며, PURGE 를 붙이면 휴지통도 거치지 않고 즉시 삭제한다.
DROP TABLE orders_csv;
DROP TABLE orders PURGE;
운영 데이터에 PURGE 를 습관적으로 붙이지 않는다. 되돌릴 수 없다.
CSV 는 잘못된 행을 걸러내지 않는다. 컬럼 수가 모자라면 뒤쪽이 NULL 이 되고, 남으면 잘린다. 적재 후 건수와 NULL 비율을 확인하는 습관이 필요하다.
인코딩은 UTF-8 을 전제한다. Windows 계열에서 만든 ANSI(CP949, Windows-1252) 파일은 깨지므로 적재 전에 변환한다.
iconv -f CP949 -t UTF-8 input.csv -o output.csv