TRANSFORM
説明
TRANSFORM
句は、ユーザーが指定したコマンドまたはスクリプトを実行して入力を変換するための、Hiveスタイルの変換クエリ仕様を指定するために使用されます。
Sparkのスクリプト変換は、2つのモードをサポートしています。
- Hiveサポートが無効: Sparkスクリプト変換は、
spark.sql.catalogImplementation=in-memory
またはSparkSession.builder.enableHiveSupport()
なしで実行できます。この場合、SparkはROW FORMAT DELIMITED
でのスクリプト変換のみを使用し、スクリプトに渡されるすべての値を文字列として扱います。 - Hiveサポートが有効: Sparkが
spark.sql.catalogImplementation=hive
で実行されるか、Spark SQLがSparkSession.builder.enableHiveSupport()
で起動されると、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
1つ以上の値、演算子、SQL関数の組み合わせで、値を生成するものを指定します。
-
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
とNULL
値を区別するために、デフォルトのNULL
値として文字列\N
を使用します。この区切り文字は、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は、JSON
形式の複合データ型を処理するためにto_json
とfrom_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
にキャストされ、ユーザー スクリプトにフィードする前にタブで結合されます。 - すべてのリテラル
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|
+-------+---------------------+