TRANSFORM
説明
TRANSFORM 句は、ユーザー指定のコマンドまたはスクリプトを実行して入力を変換するための、Hive スタイルの変換クエリ仕様を指定するために使用されます。
Spark のスクリプト変換は 2 つのモードをサポートしています
- Hive サポートが無効: Spark スクリプト変換は、
spark.sql.catalogImplementation=in-memoryを使用して、またはSparkSession.builder.enableHiveSupport()なしで実行できます。この場合、Spark はスクリプト変換をROW FORMAT DELIMITEDのみで使用し、スクリプトに渡されるすべての値を文字列として扱います。 - Hive サポートが有効:
spark.sql.catalogImplementation=hiveで Spark を実行するか、SparkSession.builder.enableHiveSupport()で Spark SQL を起動すると、Spark は Hive SerDe とROW FORMAT DELIMITEDの両方でスクリプト変換を使用できます。
構文
SELECT TRANSFORM ( expression [ , ... ] )
[ ROW FORMAT row_format ]
[ RECORDWRITER record_writer_class ]
USING command_or_script [ AS ( [ col_name [ col_type ] ] [ , ... ] ) ]
[ ROW FORMAT row_format ]
[ RECORDREADER record_reader_class ]
パラメータ
-
式 (expression)
値、演算子、SQL 関数の 1 つ以上を組み合わせたもので、結果として値が得られます。
-
row_format
入力と出力の行フォーマットを指定します。詳細な構文については、HIVE FORMAT を参照してください。
-
RECORDWRITER
カスタム RecordWriter の完全修飾クラス名を指定します。デフォルト値は
org.apache.hadoop.hive.ql.exec.TextRecordWriterです。 -
RECORDREADER
カスタム RecordReader の完全修飾クラス名を指定します。デフォルト値は
org.apache.hadoop.hive.ql.exec.TextRecordReaderです。 -
command_or_script
データを処理するコマンドまたはスクリプトへのパスを指定します。
ROW FORMAT DELIMITED の動作
Spark が ROW FORMAT DELIMITED フォーマットを使用する場合
- Spark は、デフォルトで文字
\u0001をフィールド区切り文字として使用し、この区切り文字はFIELDS TERMINATED BYによって上書きできます。 - Spark は、デフォルトで文字
\nを行区切り文字として使用し、この区切り文字はLINES TERMINATED BYによって上書きできます。 - Spark は、リテラル文字列
NULL値と区別するために、文字列\NをデフォルトのNULL値として使用します。この区切り文字はNULL DEFINED ASによって上書きできます。 - Spark は、すべての列を
STRINGにキャストし、タブで結合してからユーザー スクリプトに渡します。ARRAY/MAP/STRUCTなどの複合型の場合、Spark はto_jsonを使用して JSON 文字列にキャストし、from_jsonを使用して結果の JSON 文字列をARRAY/MAP/STRUCTデータに変換します。 COLLECTION ITEMS TERMINATED BYおよびMAP KEYS TERMINATED BYは、ARRAY/MAP/STRUCTなどの複合データを分割するための区切り文字です。Spark はto_jsonおよびfrom_jsonを使用して JSON フォーマットで複合データ型を処理します。そのため、COLLECTION ITEMS TERMINATED BYおよびMAP KEYS TERMINATED BYは、デフォルトの行フォーマットでは機能しません。- ユーザー スクリプトの標準出力は、タブ区切りの
STRING列として扱われます。文字列\Nのみを含むセルは、リテラルNULL値として再解釈され、結果のSTRING列はcol_typeで指定されたデータ型にキャストされます。 - 実際の出力列数が指定された出力列数よりも少ない場合、追加の出力列は
NULLで埋められます。たとえばoutput tabs: 1, 2 output columns: A: INT, B INT, C: INT result: +---+---+------+ | a| b| c| +---+---+------+ | 1| 2| NULL| +---+---+------+ - 実際の出力列数が指定された出力列数よりも多い場合、出力列は対応する列のみを選択し、残りの部分は破棄されます。たとえば、出力に 3 つのタブがあり、出力列が 2 つしかない場合
output tabs: 1, 2, 3 output columns: A: INT, B INT result: +---+---+ | a| b| +---+---+ | 1| 2| +---+---+ USING my_scriptの後にAS句がない場合、出力スキーマはkey: STRING, value: STRINGになります。key列には最初のタブより前のすべての文字が含まれ、value列には最初のタブより後の残りの文字が含まれます。タブがない場合、Spark はNULL値を返します。たとえばoutput tabs: 1, 2, 3 output columns: result: +-----+-------+ | key| value| +-----+-------+ | 1| 2| +-----+-------+ output tabs: 1, 2 output columns: result: +-----+-------+ | key| value| +-----+-------+ | 1| NULL| +-----+-------+
Hive SerDe の動作
Hive サポートが有効で Hive SerDe モードが使用されている場合
- Spark はデフォルトで Hive SerDe
org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDeを使用するため、列はSTRINGにキャストされ、タブで結合されてからユーザー スクリプトに渡されます。 - すべて Literal
NULL値は、リテラルNULL値とリテラル文字列NULLを区別するために、文字列\Nに変換されます。 - ユーザー スクリプトの標準出力は、タブ区切りの
STRING列として扱われます。文字列\Nのみを含むセルはNULL値として再解釈され、結果の STRING 列はcol_typeで指定されたデータ型にキャストされます。 - 実際の出力列数が指定された出力列数よりも少ない場合、追加の出力列は
NULLで埋められます。 - 実際の出力列数が指定された出力列数よりも多い場合、出力列は対応する列のみを選択し、残りの部分は破棄されます。
USING my_scriptの後にAS句がない場合、出力スキーマはkey: STRING, value: STRINGになります。key列には最初のタブより前のすべての文字が含まれ、value列には最初のタブより後の残りの文字が含まれます。タブがない場合、Spark はNULL値を返します。- これらのデフォルトは、
ROW FORMAT SERDEまたはROW FORMAT DELIMITEDを使用して上書きできます。
例
CREATE TABLE person (zip_code INT, name STRING, age INT);
INSERT INTO person VALUES
(94588, 'Zen Hui', 50),
(94588, 'Dan Li', 18),
(94588, 'Anil K', 27),
(94588, 'John V', NULL),
(94511, 'David K', 42),
(94511, 'Aryan B.', 18),
(94511, 'Lalit B.', NULL);
-- With specified output without data type
SELECT TRANSFORM(zip_code, name, age)
USING 'cat' AS (a, b, c)
FROM person
WHERE zip_code > 94511;
+-------+---------+-----+
| a | b| c|
+-------+---------+-----+
| 94588| Anil K| 27|
| 94588| John V| NULL|
| 94588| Zen Hui| 50|
| 94588| Dan Li| 18|
+-------+---------+-----+
-- With specified output with data type
SELECT TRANSFORM(zip_code, name, age)
USING 'cat' AS (a STRING, b STRING, c STRING)
FROM person
WHERE zip_code > 94511;
+-------+---------+-----+
| a | b| c|
+-------+---------+-----+
| 94588| Anil K| 27|
| 94588| John V| NULL|
| 94588| Zen Hui| 50|
| 94588| Dan Li| 18|
+-------+---------+-----+
-- Using ROW FORMAT DELIMITED
SELECT TRANSFORM(name, age)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
NULL DEFINED AS 'NULL'
USING 'cat' AS (name_age string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '@'
LINES TERMINATED BY '\n'
NULL DEFINED AS 'NULL'
FROM person;
+---------------+
| name_age|
+---------------+
| Anil K,27|
| John V,null|
| ryan B.,18|
| David K,42|
| Zen Hui,50|
| Dan Li,18|
| Lalit B.,null|
+---------------+
-- Using Hive Serde
SELECT TRANSFORM(zip_code, name, age)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim' = '\t'
)
USING 'cat' AS (a STRING, b STRING, c STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim' = '\t'
)
FROM person
WHERE zip_code > 94511;
+-------+---------+-----+
| a | b| c|
+-------+---------+-----+
| 94588| Anil K| 27|
| 94588| John V| NULL|
| 94588| Zen Hui| 50|
| 94588| Dan Li| 18|
+-------+---------+-----+
-- Schema-less mode
SELECT TRANSFORM(zip_code, name, age)
USING 'cat'
FROM person
WHERE zip_code > 94500;
+-------+----------------+
| key| value|
+-------+----------------+
| 94588| Anil K 27|
| 94588| John V \N|
| 94511| Aryan B. 18|
| 94511| David K 42|
| 94588| Zen Hui 50|
| 94588| Dan Li 18|
| 94511| Lalit B. \N|
+-------+----------------+