La instrucción SELECT TRANSFORM permite iniciar un proceso secundario específico y utilizar la entrada estándar para introducir datos en el formato requerido. Posteriormente, puede analizar sintácticamente la salida estándar del proceso secundario para obtener los datos de salida. La instrucción SELECT TRANSFORM le permite ejecutar scripts en otros lenguajes de programación sin necesidad de escribir funciones con valores de tabla definidas por el usuario (UDTF).
Descripción
El rendimiento de SELECT TRANSFORM y las UDTF varía según el escenario. Los resultados de las pruebas comparativas muestran que SELECT TRANSFORM supera a las UDTF al consultar volúmenes pequeños de datos. Sin embargo, las UDTF ofrecen mejor rendimiento que SELECT TRANSFORM cuando se consultan grandes cantidades de datos. SELECT TRANSFORM es fácil de desarrollar y resulta más adecuado para consultas ad hoc.
SELECT TRANSFORM es compatible con diversos lenguajes de programación. Esta instrucción permite escribir scripts directamente en los comandos para implementar funciones sencillas. Lenguajes como AWK, Python, Perl y Shell admiten esta operación, lo que elimina la necesidad de realizar pasos adicionales como crear archivos de script y cargar recursos. Esto simplifica el proceso de desarrollo. Para implementar funciones complejas, puede cargar archivos de script. Para obtener más información, consulte Example of calling Python scripts y Example of calling Java scripts.
A continuación se presenta una tabla con los resultados de la comparación entre UDTF y SELECT TRANSFORM en distintas dimensiones.
|
Categoría |
|
UDTF |
|
Tipo de dato |
Un proceso secundario utiliza la entrada y salida estándar para transmitir datos. Todos los datos se procesan como cadenas. Si utiliza |
Los resultados de salida y los parámetros de entrada de las UDTF admiten varios tipos de datos. |
|
Transmisión de datos |
La transmisión de datos se basa en la canalización del sistema operativo. No obstante, el tamaño de la caché de la canalización es de solo 4 KB y no se puede modificar. Si la canalización está vacía o llena, SELECT TRANSFORM invoca sistemas subyacentes para leer y escribir datos durante la transmisión. Esta instrucción ofrece un mayor rendimiento en la transmisión de datos que los programas Java. |
No existe límite en la caché de la canalización. |
|
Transmisión de parámetros constantes |
Es necesario transmitir los parámetros constantes. |
La transmisión de parámetros constantes es opcional. |
|
Proceso |
SELECT TRANSFORM admite procesos primarios y secundarios. Si el uso de recursos de cómputo es alto y el throughput de datos es bajo, |
Se utiliza un único proceso. |
|
Rendimiento |
|
El rendimiento es bajo. |
Límites
PHP y Ruby no están desplegados en los clústeres de cómputo de MaxCompute. Por lo tanto, no es posible invocar scripts de PHP ni de Ruby en MaxCompute.
Sintaxis
select transform(<arg1>, <arg2> ...)
[(row format delimited (fields terminated by <field_delimiter> (escaped by <character_escape>)) (null defined as <null_value>))]
using '<unix_command_line>'
(resources '<res_name>' (',' '<res_name>')*)
[(as <col1>, <col2> ...)]
(row format delimited (fields terminated by <field_delimiter> (escaped by <character_escape>)) (null defined as <null_value>))
Palabra clave SELECT TRANSFORM: obligatoria. Puede sustituir esta palabra clave por
maporeduce, que tienen la misma semántica. Para mayor claridad en la sintaxis, se recomienda utilizar SELECT TRANSFORM.arg1,arg2...: obligatorio. Estos parámetros especifican los datos de entrada. Sus formatos son idénticos a los de las instrucciones
SELECT. Si utiliza los formatos predeterminados, los resultados de las expresiones de cada parámetro se convierten implícitamente a valores de tipo STRING. Después, los parámetros se combinan con\ty se pasan al proceso secundario especificado.-
Cláusula ROW FORMAT: opcional. Esta cláusula permite personalizar el formato de los datos de entrada y salida.
En la sintaxis se emplean dos cláusulas ROW FORMAT. La primera define el formato de los datos de entrada, mientras que la segunda establece el formato de los datos de salida. De forma predeterminada, se usa
\tcomo delimitador de columnas,\ncomo delimitador de filas y\Npara representar valores nulos.NotaSolo se puede usar un carácter como field_delimiter o character_escape. Si especifica una cadena para estos parámetros, se utilizará únicamente el primer carácter de dicha cadena.
MaxCompute admite sintaxis en los formatos definidos por Apache Hive, tales como
inputRecordReader,outputRecordReaderySerDe. Para utilizar estas sintaxis, debe habilitar la edición de tipos de datos compatible con Hive. Para ello, agregueset odps.sql.hive.compatible=true;antes de las instrucciones SQL. Para más información sobre las sintaxis compatibles con Apache Hive, consulte la documentación de Hive.Si especifica una sintaxis compatible con Apache Hive, como
inputRecordReaderooutputRecordReader, la ejecución de las instrucciones SQL podría ser más lenta.
-
Cláusula USING: obligatoria. Esta cláusula especifica el comando utilizado para iniciar un proceso secundario.
En la mayoría de las instrucciones SQL de MaxCompute, la cláusula USING especifica recursos. Sin embargo, en la instrucción SELECT TRANSFORM, la cláusula USING indica el comando para iniciar un proceso secundario. El uso de la cláusula USING garantiza la compatibilidad con la sintaxis de Apache Hive.
La sintaxis de la cláusula USING es similar a la de un script de shell. No obstante, en lugar de ejecutar un script de shell, la cláusula USING crea un proceso secundario basado en el comando que usted especifique. Por ello, ciertas características de shell, como la redirección de entrada y salida, la canalización y los bucles, no están disponibles. Si es necesario, puede utilizar un script de shell como comando para iniciar el proceso secundario.
-
Cláusula RESOURCES: opcional. Esta cláusula define los recursos a los que puede acceder un proceso secundario. Puede utilizar uno de los siguientes métodos para especificar dichos recursos:
Utilice la cláusula RESOURCES para especificar recursos, por ejemplo:
using 'sh foo.sh bar.txt' resources 'foo.sh','bar.txt'.-
Utilice set odps.sql.session.resources para definir los recursos. Por ejemplo, puede agregar la bandera
set odps.sql.session.resources=foo.sh,bar.txt;antes de las instrucciones SQL para especificarlos.Una vez aplicada esta configuración global, todas las instrucciones SELECT TRANSFORM podrán acceder a los recursos. Separe varios archivos de recursos con comas (,).
-
Cláusula AS: opcional. Esta cláusula especifica las columnas de salida y sus tipos de datos, por ejemplo:
as(col1 bigint, col2 boolean).Si no especifica los tipos de datos para las columnas de salida, se utilizará el tipo predeterminado STRING. Por ejemplo,
AS(col1, col2)indica que las columnas de salida son de tipo STRING.Los datos de salida se obtienen al analizar sintácticamente la salida estándar del proceso secundario. Si los datos especificados no son de tipo STRING, MaxCompute invoca implícitamente la función
CASTpara convertir el tipo de dato a STRING. Durante esta conversión podría producirse una excepción en tiempo de ejecución.No puede especificar tipos de datos solo para algunas de las columnas indicadas, como en
as(col1, col2:bigint).Si omite la cláusula
AS, el campo anterior al primer\ten los datos de salida estándar será la clave, y todas las partes siguientes constituirán el valor. Esto equivale aAS(key, value).
Ejemplo de invocación de comandos de shell
Ejecute un comando de shell para generar 50 filas de datos numeradas del 1 al 50. La salida corresponde al campo data. Utilice la salida del comando de shell como entrada de SELECT TRANSFORM. Instrucción de ejemplo:
select transform(script) using 'sh' as (data)
from (
select 'for i in `seq 1 50`; do echo $i; done' as script
) t
;
-- The preceding statement is equivalent to the following statement:
select transform('for i in `seq 1 50`; do echo $i; done') using 'sh' as (data);
Se devuelve el siguiente resultado:
+------------+
| data |
+------------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 21 |
| 22 |
| 23 |
| 24 |
| 25 |
| 26 |
| 27 |
| 28 |
| 29 |
| 30 |
| 31 |
| 32 |
| 33 |
| 34 |
| 35 |
| 36 |
| 37 |
| 38 |
| 39 |
| 40 |
| 41 |
| 42 |
| 43 |
| 44 |
| 45 |
| 46 |
| 47 |
| 48 |
| 49 |
| 50 |
+------------+
Ejemplo de invocación de comandos de Python
Utilice un comando de Python para generar 50 filas de datos numeradas del 1 al 50. La salida corresponde al campo data. Utilice la salida del comando de Python como entrada de SELECT TRANSFORM. Instrucción de ejemplo:
select transform(script) using 'python' as (data)
from (
select 'for i in xrange(1, 51): print(i);' as script
) t
;
-- The preceding statement is equivalent to the following statement:
select transform('for i in xrange(1, 51): print(i);') using 'python' as (data);
Se devuelve el siguiente resultado:
+------------+
| data |
+------------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 21 |
| 22 |
| 23 |
| 24 |
| 25 |
| 26 |
| 27 |
| 28 |
| 29 |
| 30 |
| 31 |
| 32 |
| 33 |
| 34 |
| 35 |
| 36 |
| 37 |
| 38 |
| 39 |
| 40 |
| 41 |
| 42 |
| 43 |
| 44 |
| 45 |
| 46 |
| 47 |
| 48 |
| 49 |
| 50 |
+------------+
Ejemplo de invocación de comandos de AWK
Cree una tabla de prueba. Ejecute un comando de AWK para proporcionar la segunda columna de dicha tabla como salida. Los datos de salida corresponden al campo data. Utilice la salida del comando de AWK como entrada de SELECT TRANSFORM. Instrucción de ejemplo:
-- Create a test table.
create table testdata(c1 bigint,c2 bigint);
-- Insert test data into the test table.
insert into table testdata values (1,4),(2,5),(3,6);
-- Execute the SELECT TRANSFORM statement.
select transform(*) using "awk '//{print $2}'" as (data) from testdata;
Se devuelve el siguiente resultado:
+------------+
| data |
+------------+
| 4 |
| 5 |
| 6 |
+------------+
Ejemplo de invocación de comandos de Perl
Cree una tabla de prueba. Ejecute un comando de Perl para proporcionar los datos de dicha tabla como salida. Los datos de salida corresponden al campo data. Utilice la salida del comando de Perl como entrada de SELECT TRANSFORM. Instrucción de ejemplo:
-- Create a test table.
create table testdata(c1 bigint,c2 bigint);
-- Insert test data into the test table.
insert into table testdata values (1,4),(2,5),(3,6);
-- Execute the SELECT TRANSFORM statement.
select transform(testdata.c1, testdata.c2) using "perl -e 'while($input = <STDIN>){print $input;}'" from testdata;
Se devuelve el siguiente resultado:
+------------+------------+
| key | value |
+------------+------------+
| 1 | 4 |
| 2 | 5 |
| 3 | 6 |
+------------+------------+
Ejemplo de invocación de scripts de Python
-
Cree el archivo myplus.py. Instrucciones de ejemplo:
#!/usr/bin/env python import sys line = sys.stdin.readline() while line: token = line.split('\t') if (token[0] == '\\N') or (token[1] == '\\N'): print('\\N') else: print(str(token[0]) +'\t' + str(token[1])) line = sys.stdin.readline() -
Agregue el archivo de script de Python como recurso a MaxCompute.
add py ./myplus.py -f;NotaTambién puede utilizar la consola de DataWorks para agregar el archivo de Python como recurso. Para obtener más información, consulte Create and use MaxCompute resources.
-
Ejecute la instrucción
SELECT TRANSFORMpara invocar este archivo.-- Create a test table. create table testdata(c1 bigint,c2 bigint); -- Insert test data into the test table. insert into table testdata values (1,4),(2,5),(3,6); -- Execute the SELECT TRANSFORM statement. select transform (testdata.c1, testdata.c2) using 'python myplus.py' resources 'myplus.py' as (result1,result2) from testdata; -- The preceding statements are equivalent to the following statements: set odps.sql.session.resources=myplus.py; select transform (testdata.c1, testdata.c2) using 'python myplus.py' as (result1,result2) from testdata;Se devuelve el siguiente resultado:
+------------+------------+ | result1 | result2 | +------------+------------+ | 1 | 4 | | | NULL | | 2 | 5 | | | NULL | | 3 | 6 | | | NULL | +------------+------------+
Ejemplo de invocación de scripts de Java
-
Escriba un script de Java y expórtelo como el archivo Sum.jar. Código Java de ejemplo:
package com.aliyun.odps.test; import java.util.Scanner; public class Sum { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.nextLine(); String[] tokens = s.split("\t"); if (tokens.length < 2) { throw new RuntimeException("illegal input"); } if (tokens[0].equals("\\N") || tokens[1].equals("\\N")) { System.out.println("\\N"); } System.out.println(Long.parseLong(tokens[0]) + Long.parseLong(tokens[1])); } } } -
Agregue el archivo como recurso a MaxCompute.
add jar ./Sum.jar -f; -
Ejecute la instrucción
SELECT TRANSFORMpara invocar este archivo.-- Create a test table. create table testdata(c1 bigint,c2 bigint); -- Insert test data into the test table. insert into table testdata values (1,4),(2,5),(3,6); -- Execute the SELECT TRANSFORM statement. select transform(testdata.c1, testdata.c2) using 'java -cp Sum.jar com.aliyun.odps.test.Sum' resources 'Sum.jar' as cnt from testdata; -- The preceding statements are equivalent to the following statements: set odps.sql.session.resources=Sum.jar; select transform(testdata.c1, testdata.c2) using 'java -cp Sum.jar com.aliyun.odps.test.Sum' as cnt from testdata;Se devuelve el siguiente resultado:
+-----+ | cnt | +-----+ | 5 | | 7 | | 9 | +-----+
Java y Python cuentan con un framework UDTF listo para usar. Sin embargo, SELECT TRANSFORM facilita la escritura de scripts. SELECT TRANSFORM no requiere dependencias adicionales ni impone requisitos de formato, e incluso permite utilizar directamente scripts sin conexión. El directorio para guardar scripts de Java sin conexión se obtiene de la variable de entorno JAVA_HOME. El directorio para guardar scripts de Python sin conexión se obtiene de la variable de entorno PYTHON_HOME.
Ejemplo de invocación de scripts en serie
Puede ejecutar instrucciones SELECT TRANSFORM en serie. Para realizar esta operación, utilice las cláusulas DISTRIBUTE BY y SORT BY para preprocesar los datos de entrada. Instrucción de ejemplo:
select transform(key, value) using '<cmd2>' from
(
select transform(*) using '<cmd1>' from
(
select * from testdata distribute by c2 sort by c1
) t distribute by key sort by value
) t2;
cmd1 y cmd2 son los comandos utilizados para iniciar los procesos secundarios.
También puede utilizar las palabras clave map y reduce para ejecutar instrucciones SELECT TRANSFORM en serie.
@a := select * from data distribute by col2 sort by col1;
@b := map * using 'cmd1' distribute by col1 sort by col2 from @a;
reduce * using 'cmd2' from @b;