TeradataBinarySerde
TeradataBinarySerde
TeradataBinarySerde는 Teradata의 바이너리 데이터를 Hive 테이블로 읽거나 쓸 수 있게 해주는 SerDe예요. TPT( Teradata Parallel Transporter)나 BTEQ( Basic Teradata Query )로 내보낸 gzip 압축 데이터 파일을 Hive에서 직접 사용할 수 있게 합니다.
출처: 문서
본문
사용 가능 버전 (Availability)
TeradataBinarySerDe는 Hive 2.4 이상에서 사용할 수 있어요. (가장 이른 버전은 CSVSerde)
개요 (Overview)
Teradata는 TPT 또는 BTEQ를 사용해 gzip으로 압축된 데이터 파일을 매우 빠른 속도로 내보내고 가져올 수 있어요. 하지만 이런 바이너리 파일은 Teradata의 독점 형식으로 인코딩되어, 사용자 정의 SerDe 없이는 Hive가 직접 소비할 수 없습니다. TeradataBinarySerde는 사용자가 Teradata 바이너리 데이터를 Hive 테이블로 읽거나 쓸 수 있게 해줘요.
- TPT/BTEQ로 내보내 Hive에 등록한 Teradata 바이너리 데이터 파일을 직접 소비
- Hive에서 Teradata 바이너리 데이터 파일을 생성해 TPT/BTEQ로 Teradata에 직접 로드
내보내는 방법 (How to export)
TeradataBinarySerde는 다음 제약과 함께 'Formatted' 또는 'Formatted4' 모드의 데이터 파일을 지원합니다.
INDICDATA형식을 사용 (DATA를 사용하지 말 것)- 최대 소수 자릿수(decimal digits) = 38 (18을 사용하지 말 것)
- 날짜 형식 = integer (ANSI를 사용하지 말 것)
TPT FastExport 사용하기
TPT FastExport를 호출하는 bash 스크립트 예시입니다.
query_table=foo.teradata_binary_table
data_date=20180108
select_statement="SELECT * FROM $query_table WHERE transaction_date BETWEEN DATE '2018-01-01' AND DATE '2018-01-08' AND is_deleted=0"
select_statement=${select_statement//\'/\'\'} # Do not put double quote here
output_path=/data/foo/bar/${data_date}
num_chunks=4
tbuild -C -f $td_export_template_file -v ${tpt_job_var_file} \
-u "ExportSelectStmt='${select_statement}',FormatType=Formatted,DataFileCount=${num_chunks},
FileWriterDirectoryPath='${output_path},FileWriterFileName='${query_table}.${data_date}.teradata',
SourceTableName='${query_table}'"
td_export_template_file은 적절한 Format, MaxDecimalDigits, DateForm이 들어간 아래와 같은 형태입니다.
USING CHARACTER SET UTF8
DEFINE JOB EXPORT_TO_BINARY_FORMAT
DESCRIPTION 'Export to the INDICDATA file'
(
/* https://www.info.teradata.com/HTMLPubs/DB_TTU_16_00/Load_and_Unload_Utilities/B035-2436%E2%80%90086K/2436ch03.05.3.html */
APPLY TO OPERATOR ($FILE_WRITER()[@DataFileCount] ATTR
(
IndicatorMode = 'Y',
OpenMode = 'Write',
Format = @FormatType,
DirectoryPath = @FileWriterDirectoryPath,
FileName = @FileWriterFileName,
IOBufferSize = 2048000
)
)
SELECT * FROM OPERATOR ($EXPORT()[1] ATTR
(
SelectStmt = @ExportSelectStmt,
MaxDecimalDigits = 38,
DateForm = 'INTEGERDATE', /* ANSIDATE is hard to load in BTEQ */
SpoolMode = 'NoSpool',
TdpId = @SourceTdpId,
UserName = @SourceUserName,
UserPassword = @SourceUserPassword,
QueryBandSessInfo = 'Action=TPT_EXPORT;SourceTable=@SourceTableName;Format=@FormatType;'
)
);
);
로그인 자격 증명은 명령줄이 아니라 tpt_job_var_file에 제공됩니다.
SourceUserName=<td_use>
,SourceUserPassword=<td_pass>
,SourceTdpId=<td_pid>
BTEQ 사용하기
BTEQ 스크립트는 적절한 INDICDATA, Format, MaxDecimalDigits, DateForm이 들어간 아래와 같은 형태예요. 기본적으로 recordlength=max64(Formatted)가 적용되므로, 'Formatted4' 모드가 필요하면 MAX1MB를 명시적으로 지정해야 합니다.
SET SESSION DATEFORM=INTEGERDATE;
.SET SESSION CHARSET UTF8
.decimaldigits 38
.export indicdata recordlength=max1mb file=td_data_with_1mb_rowsize.dat
select * from foo.teradata_binary_table order by test_int;
.export reset
가져오는 방법 (How to import)
BTEQ 사용하기
유니코드를 사용할 때 CHAR(n) 컬럼은 USING() 절에서 CHAR(n x 3)으로 지정해야 해요. 예를 들어 test_char가 DDL에서 CHAR(1) CHARACTER SET UNICODE로 정의됐다면, BTEQ로 로드할 때 최대 3바이트를 차지하므로 USING()에 CHAR(3)으로 나타납니다. n x 3 규칙을 적용하지 않으면 BTEQ가 "Failure 2673 The source parcel length does not match data that was defined" 같은 오류를 만날 수 있어요.
RECORDLENGTH=MAX1MB 데이터 파일을 로드하는 샘플 BTEQ 스크립트:
SET SESSION DATEFORM=INTEGERDATE;
.SET SESSION CHARSET UTF8
.decimaldigits 38
.IMPORT INDICDATA RECORDLENGTH=MAX1MB FILE=td_data_with_1mb_rowsize.teradata
.REPEAT *
USING(
test_tinyint BYTEINT,
test_smallint SMALLINT,
test_int INTEGER,
test_bigint BIGINT,
test_double FLOAT,
test_decimal DECIMAL(15,2),
test_date DATE,
test_timestamp TIMESTAMP(6),
test_char CHAR(3), -- CHAR(1) will occupy 3 bytes
test_varchar VARCHAR(40),
test_binary VARBYTE(500)
)
INSERT INTO foo.stg_teradata_binary_table
(
test_tinyint, test_smallint, test_int, test_bigint, test_double, test_decimal,
test_date, test_timestamp, test_char, test_varchar, test_binary
)
values (
:test_tinyint,
:test_smallint,
:test_int,
:test_bigint,
:test_double,
:test_decimal,
:test_date,
:test_timestamp,
:test_char,
:test_varchar,
:test_binary
);
.IMPORT RESET
TPT FastLoad 사용하기
tbuild는 여러 gzip 파일을 병렬로 로드할 수 있어서, TPT는 대용량 데이터 파일을 벌크 로드하는 가장 좋은 선택이에요. TPT FastLoad를 호출하는 bash 스크립트 예시입니다.
staging_database=foo
staging_table=stg_table_name_up_to_30_chars
table_name_less_than_26chars=stg_table_name_up_to_30_c
file_dir=/data/foo/bar
job_id=<my_job_execution_id>
tbuild -C -f $td_import_template_file -v ${tpt_job_var_file} \
-u "TargetWorkingDatabase='${staging_database}',TargetTable='${staging_table}',
SourceDirectoryPath='${file_dir}',SourceFileName='*.teradata.gz',
FileInstances=8,LoadInstances=1,
Substr26TargetTable='${table_name_less_than_26chars}',
TargetQueryBandSessInfo='TptLoad=${staging_table};JobId=${job_id};'"
td_import_template_file은 다음과 같은 형태입니다.
USING CHARACTER SET @Characterset
DEFINE JOB LOAD_JOB
DESCRIPTION 'Loading Data From File To Teradata Table'
(
set LogTable=@TargetWorkingDatabase||'.'||@Substr26TargetTable||'_LT';
set ErrorTable1=@TargetWorkingDatabase||'.'||@Substr26TargetTable||'_ET';
set ErrorTable2=@TargetWorkingDatabase||'.'||@Substr26TargetTable||'_UT';
set WorkTable=@TargetWorkingDatabase||'.'||@Substr26TargetTable||'_WT';
set ErrorTable=@TargetWorkingDatabase||'.'||@Substr26TargetTable||'_ET';
set LoadPrivateLogName=@TargetTable||'_load.log'
set UpdatePrivateLogName=@TargetTable||'_update.log'
set StreamPrivateLogName=@TargetTable||'_stream.log'
set InserterPrivateLogName=@TargetTable||'_inserter.log'
set FileReaderPrivateLogName=@TargetTable||'_filereader.log'
STEP PRE_PROCESSING_DROP_ERROR_TABLES
(
APPLY
('release mload '||@TargetTable||';'),
('drop table '||@LogTable||';'),
('drop table '||@ErrorTable||';'),
('drop table '||@ErrorTable1||';'),
('drop table '||@ErrorTable2||';'),
('drop table '||@WorkTable||';')
TO OPERATOR ($DDL);
);
STEP LOADING
(
APPLY $INSERT TO OPERATOR ($LOAD() [@LoadInstances])
SELECT * FROM OPERATOR ($FILE_READER() [@FileInstances]);
);
);
tpt_job_var_file에 SourceFormat, DateForm, MaxDecimalDigits 같은 올바른 값을 설정하세요. 예:
Characterset='UTF8'
,DateForm='integerDate'
,MaxDecimalDigits=38
,TargetErrorLimit=100
,TargetErrorList=['3807','2580', '3706']
,TargetBufferSize=1024
,TargetDataEncryption='off'
,SourceOpenMode='Read'
,SourceFormat='Formatted'
,SourceIndicatorMode='Y'
,SourceMultipleReaders='Y'
,LoadBufferSize=1024
,UpdateBufferSize=1024
,LoadInstances=1
,TargetTdpId=<td_pid>
,TargetUserName=<td_user>
,TargetUserPassword=<td_pass>
사용법 (Usage) — 테이블 생성
특정 Teradata 속성으로 테이블 생성:
CREATE TABLE `teradata_binary_table_1mb`(
`test_tinyint` tinyint,
`test_smallint` smallint,
`test_int` int,
`test_bigint` bigint,
`test_double` double,
`test_decimal` decimal(15,2),
`test_date` date,
`test_timestamp` timestamp,
`test_char` char(1),
`test_varchar` varchar(40),
`test_binary` binary
)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.teradata.TeradataBinarySerde'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.TeradataBinaryFileInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.TeradataBinaryFileOutputFormat'
TBLPROPERTIES (
'teradata.timestamp.precision'='6',
'teradata.char.charset'='UNICODE',
'teradata.row.length'='1MB'
);
기본 Teradata 속성:
'teradata.timestamp.precision'='6',
'teradata.char.charset'='UNICODE',
'teradata.row.length'='64KB'
Table Properties
| Property Name | Property Value | Set Default | Note |
|---|---|---|---|
| teradata.row.length | (64KB, 1MB) | 64KB | 64KB는 Formatted 모드, 1MB는 Formatted4 모드에 해당 |
| teradata.char.charset | (UNICODE, LATIN) | UNICODE | CHAR 데이터 타입당 바이트 수 결정. UNICODE는 문자당 3바이트, LATIN은 문자당 2바이트. 모든 CHAR 타입 필드는 이 속성으로 제어됨 (별도 지정 미지원) |
| teradata.timestamp.precision | 0-6 | 6 | TIMESTAMP 데이터 타입의 바이트 수 결정. 모든 TIMESTAMP 필드는 이 속성으로 제어됨 (별도 지정 미지원) |
Teradata → Hive 타입 변환
| Teradata Data Type | Teradata Data Type Definition | Hive Type | Hive Data Type Definition | Note |
|---|---|---|---|---|
| DATE | DATE | DATE | DATE | |
| TIMESTAMP | TIMESTAMP(X) | TIMESTAMP | TIMESTAMP | TIMESTAMP precision 디코딩은 테이블 속성 teradata.timestamp.precision으로 제어 |
| BYTEINT | BYTEINT | TINYINT | TINYINT | |
| SMALLINT | SMALLINT | SMALLINT | SMALLINT | |
| INTEGER | *INTEGER |
INT | *INT |
|
| BIGINT | BIGINT | BIGINT | BIGINT | |
| FLOAT | FLOAT | DOUBLE | DOUBLE | |
| DECIMAL | DECIMAL(N,M)** – 기본 DECIMAL(5, 0) | DECIMAL | DECIMAL(N,M)** – 기본 DECIMAL(10, 0) | |
| VARCHAR | VARCHAR(X) | VARCHAR | VARCHAR(X) | |
| CHAR | CHAR(X) | CHAR | CHAR(X) | 각 CHAR의 디코딩은 테이블 속성 teradata.char.charset으로 제어 |
| VARBYTE | VARBYTE(X) | BINARY | BINARY |
Serde 제약 (Serde Restriction)
TeradataBinarySerde에는 몇 가지 제약이 있어요.
- 위에 나열된 단순 데이터 타입만 지원하며,
INTERVAL,TIME,NUMBER,CLOB,BLOB같은 Teradata의 다른 타입은 아직 지원하지 않습니다. ARRAY,MAP같은 복합 데이터 타입은 지원하지 않아요.
더 알아보기 (Learn more)
Teradata의 독점 바이너리 파일을 Hive에서 직접 다룰 수 있게 해주는 SerDe예요. 내보내기(Formatted/Formatted4)와 가져오기 양쪽을 지원하며, 사용 전에 teradata.row.length·teradata.char.charset·teradata.timestamp.precision 속성을 제대로 설정해야 합니다.