HDFS 에 파일을 올리고 그 디렉터리를 가리키는 외부 테이블을 만든다.
hdfs dfs -mkdir -p /user/hadoop/data
hdfs dfs -put local_file.csv /user/hadoop/data/
CREATE EXTERNAL TABLE my_table (
col1 STRING,
col2 STRING,
col3 STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
LOCATION '/user/hadoop/data/'
TBLPROPERTIES ('skip.header.line.count' = '1');
FIELDS TERMINATED BY 에 탭은 '\t', 쉼표는 ',' 를 준다. skip.header.line.count 는 파일마다 앞 n 줄을 건너뛴다.
파일을 나중에 넣거나 바꿨다면 메타데이터를 갱신한다.
REFRESH my_table;
INVALIDATE METADATA my_table;
REFRESH 는 파일 목록과 블록 위치만 다시 읽는 가벼운 연산이고, INVALIDATE METADATA 는 테이블 메타데이터 전체를 버리고 다시 가져오는 무거운 연산이다. 파일만 추가했다면 REFRESH 로 충분하다.
Impala 는 텍스트 파일을 UTF-8 로 해석한다. Windows 에서 만든 ANSI(CP949, Windows-1252) 파일을 그대로 올리면 한글과 특수문자가 깨지거나 물음표로 나온다. 문자셋을 지정하는 테이블 속성은 없으므로 적재 전에 변환한다.
iconv -f CP949 -t UTF-8 input.csv -o output.csv
file -i output.csv
with open("input.csv", "r", encoding="cp949") as src, \
open("output.csv", "w", encoding="utf-8") as dst:
dst.write(src.read())
변환 후 hdfs dfs -put 으로 올리고 REFRESH 한다.
ROW FORMAT DELIMITED 는 따옴표 안의 구분자를 인식하지 못한다. 값에 쉼표가 들어 있는 CSV 라면 Hive 에서 OpenCSVSerde 로 테이블을 만들고 Impala 에서 조회하거나, 전처리 단계에서 다른 구분자로 바꾼다. Impala 는 SerDe 를 직접 지정해 테이블을 만들 수 없고, Hive 가 만든 테이블을 읽을 수는 있다.
텍스트 테이블은 스캔이 느리다. 반복 조회한다면 한 번 읽어 Parquet 으로 저장한다.
CREATE TABLE my_table_parquet STORED AS PARQUET AS
SELECT
CAST(col1 AS BIGINT) AS id,
col2 AS name,
CAST(col3 AS DOUBLE) AS amount
FROM my_table;
COMPUTE STATS my_table_parquet;
EXTERNAL 로 만든 테이블은 DROP TABLE 해도 HDFS 파일이 남는다. 메타데이터만 지운다. 데이터까지 지우려면 관리형 테이블로 만들거나 HDFS 에서 직접 지운다.
PURGE 는 휴지통을 건너뛰고 즉시 삭제하는 옵션이며, 외부 테이블에는 기본적으로 파일을 지우지 않으므로 의미가 없다. 운영 테이블에서 습관적으로 쓰지 않는다.
DROP TABLE my_table;