Funciones de agregación definidas por el usuario
Para obtener asistencia durante la vista previa, envía un correo electrónico a bigquery-sql-preview-support@google.com.
En este documento, se describe cómo crear, llamar y borrar funciones de agregación definidas por el usuario (UDAF) en BigQuery.
Una UDAF te permite crear una función agregada mediante una expresión que contiene código. Una UDAF acepta columnas de entrada, realiza un cálculo en un grupo de filas a la vez y, luego, muestra el resultado de ese cálculo como un valor único.
Crea una UDAF de SQL
En esta sección, se describen las diversas formas en que puedes crear una UDAF de SQL persistente o temporal en BigQuery.
Crea una UDAF de SQL persistente
Puedes crear un UDAF de SQL que sea persistente, lo que significa que puedes reutilizar la UDAF en varias consultas. Es seguro llamar a las UDAF persistentes cuando se comparten entre propietarios. Las UDAF no pueden mutar datos, comunicarse con sistemas externos ni enviar registros a la observabilidad de Google Cloud o a aplicaciones similares.
Para crear un UDAF persistente, usa la declaración CREATE AGGREGATE FUNCTION
sin la palabra clave TEMP
o TEMPORARY
. Debes incluir el conjunto de datos en la ruta de la función.
Por ejemplo, la siguiente consulta crea una UDAF persistente que se llama ScaledAverage
:
CREATE AGGREGATE FUNCTION myproject.mydataset.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Crea una UDAF de SQL temporal
Puedes crear una UDAF de SQL que sea temporal, lo que significa que la UDAF solo existe dentro del alcance de una sola consulta, secuencia de comandos, sesión o procedimiento.
Para crear un UDAF temporal, usa la declaración CREATE AGGREGATE FUNCTION
con la palabra clave TEMP
o TEMPORARY
.
Por ejemplo, la siguiente consulta crea una UDAF temporal que se llama ScaledAverage
:
CREATE TEMP AGGREGATE FUNCTION ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Usa parámetros agregados y no agregados
Puedes crear una UDAF de SQL que tenga parámetros agregados y no agregados.
Por lo general, las UDAF agregan parámetros de función en todas las filas de un grupo.
Sin embargo, puedes especificar un parámetro de función como no agregado con la palabra clave NOT AGGREGATE
.
Un parámetro de función sin agregación es un parámetro de función escalar con un valor constante para todas las filas de un grupo. Un parámetro de función sin agregación válido debe ser un literal. Dentro de la definición de UDAF, los parámetros de funciones de agregación solo pueden aparecer como argumentos de funciones para agregar llamadas a funciones. Las referencias a parámetros de funciones no agregadas pueden aparecer en cualquier parte de la definición de la UDAF.
Por ejemplo, la siguiente función contiene un parámetro agregado llamado dividend
y un parámetro no agregado llamado divisor
:
-- Create the function. CREATE TEMP AGGREGATE FUNCTION ScaledSum( dividend FLOAT64, divisor FLOAT64 NOT AGGREGATE) RETURNS FLOAT64 AS ( SUM(dividend) / divisor );
Usa el proyecto predeterminado en el cuerpo de la función
En el cuerpo de una UDAF de SQL, cualquier referencia a entidades de BigQuery, como tablas o vistas, debe incluir el ID del proyecto, a menos que la entidad resida en el mismo proyecto que contiene la UDAF.
Por ejemplo, considera la siguiente declaración:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM dataset_a.my_table ) );
Si ejecutas la instrucción anterior en el proyecto project1
, la declaración tiene éxito porque my_table
existe en project1
. Sin embargo, si ejecutas la instrucción anterior desde un proyecto diferente, la instrucción fallará.
Para corregir el error, incluye el ID del proyecto en la referencia de la tabla:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM project1.dataset_a.my_table ) );
También puedes hacer referencia a una entidad en un proyecto o conjunto de datos diferente del que creaste la función:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM project2.dataset_c.my_table ) );
Crea una UDAF de JavaScript
En esta sección, se describen las diversas formas en las que puedes crear una UDAF de JavaScript en BigQuery. Debes tener en cuenta algunas reglas cuando se crea una UDAF de JavaScript:
El cuerpo de la UDAF de JavaScript debe ser un literal de cadena entre comillas que represente el código de JavaScript. Para obtener más información acerca de los diferentes tipos de literales de cadena entre comillas que puedes usar, consulta Formatos para literales entrecomillados.
Solo se permiten ciertas codificaciones de tipos. Para obtener más información, consulta Codificaciones de tipos de SQL permitidas en una UDAF de JavaScript.
El cuerpo de la función de JavaScript debe incluir cuatro funciones de JavaScript que inicializan, agregan, combinan y finalizan los resultados de la UDAF de JavaScript (
initialState
,aggregate
,merge
yfinalize
). Para obtener más información, consulta Codificaciones de tipos de SQL permitidas en una UDAF de JavaScript.Cualquier valor que muestre la función
initialState
o que quede en el argumentostate
después de que se llame a la funciónaggregate
omerge
debe ser serializable. Si deseas trabajar con datos de agregación no serializables, como funciones o campos de símbolos, debes usar las funcionesserialize
ydeserialize
incluidas. Para obtener más información, consulta Serializa y deserializa datos en una UDAF de JavaScript.
Crea una UDAF de JavaScript persistente
Puedes crear una UDAF de SQL que sea persistente, lo que significa que puedes reutilizar la UDAF en varias consultas. Es seguro llamar a las UDAF persistentes cuando se comparten entre propietarios. Las UDAF no pueden mutar datos, comunicarse con sistemas externos ni enviar registros a la observabilidad de Google Cloud o a aplicaciones similares.
Para crear una UDAF persistente, usa la
declaración CREATE AGGREGATE FUNCTION
sin la
palabra clave TEMP
o TEMPORARY
. Debes incluir el conjunto de datos en la ruta de la función.
En la siguiente consulta, se crea una UDAF de JavaScript persistente que se llama
SumPositive
:
CREATE OR REPLACE AGGREGATE FUNCTION my_project.my_dataset.SumPositive(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS r''' export function initialState() { return {sum: 0} } export function aggregate(state, x) { if (x > 0) { state.sum += x; } } export function merge(state, partialState) { state.sum += partialState.sum; } export function finalize(state) { return state.sum; } '''; -- Call the JavaScript UDAF. WITH numbers AS ( SELECT * FROM UNNEST([1.0, -1.0, 3.0, -3.0, 5.0, -5.0]) AS x) SELECT my_project.my_dataset.SumPositive(x) AS sum FROM numbers; /*-----* | sum | +-----+ | 9.0 | *-----*/
Crea una UDAF de JavaScript temporal
Puedes crear una UDAF de JavaScript que sea temporal, lo que significa que la UDAF solo existe dentro del alcance de una sola consulta, secuencia de comandos, sesión o procedimiento.
Para crear un UDAF temporal, usa la declaración CREATE AGGREGATE FUNCTION
con la palabra clave TEMP
o TEMPORARY
.
En la siguiente consulta, se crea una UDAF de JavaScript temporal que se llama
SumPositive
:
CREATE TEMP AGGREGATE FUNCTION SumPositive(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS r''' export function initialState() { return {sum: 0} } export function aggregate(state, x) { if (x > 0) { state.sum += x; } } export function merge(state, partialState) { state.sum += partialState.sum; } export function finalize(state) { return state.sum; } '''; -- Call the JavaScript UDAF. WITH numbers AS ( SELECT * FROM UNNEST([1.0, -1.0, 3.0, -3.0, 5.0, -5.0]) AS x) SELECT SumPositive(x) AS sum FROM numbers; /*-----* | sum | +-----+ | 9.0 | *-----*/
Incluye parámetros no agregados en una UDAF de JavaScript
Puedes crear una UDAF de JavaScript que tenga parámetros agregados y no agregados.
Por lo general, las UDAF agregan parámetros de función en todas las filas de un grupo.
Sin embargo, puedes especificar un parámetro de función como no agregado con la palabra clave NOT AGGREGATE
.
Un parámetro de función sin agregación es un parámetro de función escalar con un valor constante para todas las filas de un grupo. Un parámetro de función sin agregación válido debe ser un literal. Dentro de la definición de UDAF, los parámetros de funciones de agregación solo pueden aparecer como argumentos de funciones para agregar llamadas a funciones. Las referencias a parámetros de funciones no agregadas pueden aparecer en cualquier parte de la definición de la UDAF.
En el siguiente ejemplo, la UDAF de JavaScript contiene un parámetro
agregado llamado s
y un parámetro no agregado llamado delimiter
:
CREATE TEMP AGGREGATE FUNCTION JsStringAgg( s STRING, delimiter STRING NOT AGGREGATE) RETURNS STRING LANGUAGE js AS r''' export function initialState() { return {strings: []} } export function aggregate(state, s) { state.strings.push(s); } export function merge(state, partialState) { state.strings = state.strings.concat(partialState.strings); } export function finalize(state, delimiter) { return state.strings.join(delimiter); } '''; -- Call the JavaScript UDAF. WITH strings AS ( SELECT * FROM UNNEST(["aaa", "bbb", "ccc", "ddd"]) AS values) SELECT JsStringAgg(values, '.') AS result FROM strings; /*-----------------* | result | +-----------------+ | aaa.bbb.ccc.ddd | *-----------------*/
Serializa y deserializa datos en una UDAF de JavaScript
BigQuery debe serializar
cualquier objeto que muestre la función initialState
o que quede en el
argumento state
después de que se llame a la función aggregate
o merge
.
BigQuery admite
la serialización de un objeto si todos los campos son uno de los siguientes:
- Un valor básico de JavaScript (por ejemplo:
2
,"abc"
,null
,undefined
). - Un objeto de JavaScript para el que BigQuery admite la serialización de todos los valores de campo.
- Un array de JavaScript para el que BigQuery admite la serialización de todos los elementos.
Los siguientes valores de retorno son serializables:
export function initialState() {
return {a: "", b: 3, c: null, d: {x: 23} }
}
export function initialState() {
return {value: 2.3};
}
Los siguientes valores de retorno no se pueden serializar:
export function initialState() {
return {
value: function() {return 6;}
}
}
export function initialState() {
return 2.3;
}
Si deseas trabajar con estados de agregación no serializables,
la UDAF de JavaScript debe incluir las funciones serialize
y deserialize
.
La función serialize
convierte el estado de agregación en un objeto
serializable. La función deserialize
vuelve a convertir el objeto serializable en
un estado de agregación.
En el siguiente ejemplo, una biblioteca externa calcula las sumas a través de una interfaz:
export class SumAggregator { constructor() { this.sum = 0; } update(value) { this.sum += value; } getSum() { return this.sum; } }
La siguiente consulta no se ejecuta porque el objeto de clase SumAggregator
no
se puede serializar con BigQuery debido a la presencia de funciones
dentro de la clase.
CREATE TEMP AGGREGATE FUNCTION F(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS r''' class SumAggregator { constructor() { this.sum = 0; } update(value) { this.sum += value; } getSum() { return this.sum; } } export function initialState() { return new SumAggregator(); } export function aggregate(agg, value) { agg.update(value); } export function merge(agg1, agg2) { agg1.update(agg2.getSum()); } export function finalize(agg) { return agg.getSum(); } '''; --Error: getSum is not a function SELECT F(x) AS results FROM UNNEST([1,2,3,4]) AS x;
Si agregas las funciones serialize
y deserialize
a la consulta anterior,
la consulta se ejecuta porque el objeto de clase SumAggregator
se convierte en un
objeto que se puede serializar con BigQuery y, luego, de nuevo en un
objeto de clase SumAggregator
.
CREATE TEMP AGGREGATE FUNCTION F(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS r''' class SumAggregator { constructor() { this.sum = 0; } update(value) { this.sum += value; } getSum() { return this.sum; } } export function initialState() { return new SumAggregator(); } export function aggregate(agg, value) { agg.update(value); } export function merge(agg1, agg2) { agg1.update(agg2.getSum()); } export function finalize(agg) { return agg.getSum(); } export function serialize(agg) { return {sum: agg.getSum()}; } export function deserialize(serialized) { var agg = new SumAggregator(); agg.update(serialized.sum); return agg; } '''; SELECT F(x) AS results FROM UNNEST([1,2,3,4]) AS x; /*-----------------* | results | +-----------------+ | 10.0 | *-----------------*/
Para obtener más información acerca de las funciones de serialización, consulta Funciones opcionales de serialización de JavaScript.
Incluye variables globales y funciones personalizadas en una UDAF de JavaScript
El cuerpo de la función de JavaScript puede incluir código de JavaScript personalizado, como variables globales de JavaScript y funciones personalizadas.
Las variables globales se ejecutan cuando se carga JavaScript
en BigQuery y antes de que se ejecute la función initialState
.
Las variables globales pueden ser útiles si necesitas realizar un trabajo de inicialización
único que no debe repetirse para cada grupo de agregación, como sería el caso con
las funciones initialState
, aggregate
, merge
y finalize
.
No uses variables globales para almacenar el estado de agregación. En su lugar, limita el estado de agregación a los objetos que se pasan a las funciones exportadas. Usa variables globales solo para almacenar en caché las operaciones costosas que no son específicas de ninguna operación de agregación en particular.
En la siguiente consulta, la función SumOfPrimes
calcula una suma, pero solo
se incluyen números primos en el cálculo. En el cuerpo de la función de JavaScript,
hay dos variables globales, primes
y maxTested
, que se inicializan
primero. Además, hay una función personalizada llamada isPrime
que verifica si
un número es primo.
CREATE TEMP AGGREGATE FUNCTION SumOfPrimes(x INT64) RETURNS INT64 LANGUAGE js AS r''' var primes = new Set([2]); var maxTested = 2; function isPrime(n) { if (primes.has(n)) { return true; } if (n <= maxTested) { return false; } for (var k = 2; k < n; ++k) { if (!isPrime(k)) { continue; } if ((n % k) == 0) { maxTested = n; return false; } } maxTested = n; primes.add(n); return true; } export function initialState() { return {sum: 0}; } export function aggregate(state, x) { x = Number(x); if (isPrime(x)) { state.sum += x; } } export function merge(state, partialState) { state.sum += partialState.sum; } export function finalize(state) { return state.sum; } '''; -- Call the JavaScript UDAF. WITH numbers AS ( SELECT * FROM UNNEST([10, 11, 13, 17, 19, 20]) AS x) SELECT SumOfPrimes(x) AS sum FROM numbers; /*-----* | sum | +-----+ | 60 | *-----*/
Incluye bibliotecas de JavaScript
Puedes extender tus UDAF de JavaScript con la opción library
en la
cláusula OPTIONS
. Esta opción te permite especificar bibliotecas de código externas para la
UDAF de JavaScript y, luego, importar esas bibliotecas con la declaración import
.
En el siguiente ejemplo, el código en bar.js
está disponible para cualquier código en el
cuerpo de la función de la UDAF de JavaScript:
CREATE TEMP AGGREGATE FUNCTION JsAggFn(x FLOAT64) RETURNS FLOAT64 LANGUAGE js OPTIONS (library = ['gs://foo/bar.js']) AS r''' import doInterestingStuff from 'bar.js'; export function initialState() { return ... } export function aggregate(state, x) { var result = doInterestingStuff(x); ... } export function merge(state, partial_state) { ... } export function finalize(state) { return ...; } ''';
Estructura de JavaScript obligatoria
A diferencia de una UDF de JavaScript, en la que el cuerpo de la función es JavaScript de formato libre que se ejecuta para cada fila, el cuerpo de la función para una UDAF de JavaScript es un módulo de JavaScript que contiene algunas funciones integradas exportadas, que se invocan en varias etapas del proceso de agregación. Algunas de estas funciones integradas son obligatorias, mientras que otras son opcionales. También puedes agregar tus funciones de JavaScript.
Funciones de agregación de JavaScript obligatorias
Puedes incluir tus funciones de JavaScript, pero el cuerpo de la función debe incluir las siguientes funciones exportables de JavaScript:
initialState([nonAggregateParam])
: muestra un objeto de JavaScript que representa un estado de agregación en el que aún no se agregaron filas.aggregate(state, aggregateParam[, ...][, nonAggregateParam])
: agrega una fila de datos, lo que actualiza el estado para almacenar el resultado de la agregación. No muestra un valor.merge(state, partialState, [nonAggregateParam])
: combina el estado de agregaciónpartialState
en el estado de agregaciónstate
. Esta función se usa cuando el motor agrega diferentes secciones de datos en paralelo y necesita combinar los resultados. No muestra un valor.finalize(finalState, [nonAggregateParam])
: muestra el resultado final de la función agregada, según un estado de agregación finalfinalState
.
Para obtener más información acerca de las funciones obligatorias, consulta Funciones requeridas en una UDAF de JavaScript.
Funciones opcionales de serialización de JavaScript
Si deseas trabajar con estados de agregación no serializables, la
UDAF de JavaScript debe proporcionar las funciones serialize
y deserialize
.
La función serialize
convierte el estado de agregación en un
objeto que se puede serializar con BigQuery. La función deserialize
vuelve a convertir el
objeto que se puede serializar con BigQuery en un estado de agregación.
serialize(state)
: muestra un objeto serializable que contiene la información en el estado de agregación que se deserializará a través de la funcióndeserialize
.deserialize(serializedState)
: deserializaserializedState
(anteriormente serializado por la funciónserialize
) en un estado de agregación que puede pasarse a las funcionesserialize
,aggregate
,merge
ofinalize
.
Para obtener más información acerca de las funciones de serialización de JavaScript integradas, consulta Funciones de serialización para una UDAF de JavaScript.
Para aprender a serializar y deserializar datos con una UDAF de JavaScript, consulta Serializa y deserializa datos en una UDAF de JavaScript.
Codificaciones de tipos de SQL permitidas en una UDAF de JavaScript
En las UDAF de JavaScript, los siguientes tipos de datos de GoogleSQL compatibles representan tipos de datos de JavaScript de la siguiente manera:
Tipo de datos de GoogleSQL |
Tipo de dato de JavaScript |
Notas |
---|---|---|
ARRAY |
Array |
No se admite un array de arrays. Para evitar esta
limitación, usa los
tipos de datos
Array<Object<Array>> (JavaScript) y
ARRAY<STRUCT<ARRAY>> (GoogleSQL).
|
BIGNUMERIC
|
Number o String
|
Igual que NUMERIC .
|
BOOL |
Boolean |
|
BYTES |
Uint8Array |
|
DATE |
Date |
|
FLOAT64 |
Number |
|
INT64 |
BigInt |
|
JSON |
Varios tipos |
El tipo de datos JSON de GoogleSQL se puede convertir
en un Object , Array o en otro
tipo de datos de JavaScript compatible con GoogleSQL.
|
NUMERIC
|
Number o String
|
Si un valor NUMERIC se puede representar de forma exacta como un valor de
punto flotante IEEE 754
(rango [-253, 253] )
y no tiene una parte fraccionaria, se codifica como un tipo de datos
Number ; de lo contrario, se codifica como un tipo de datos String .
|
STRING |
String |
|
STRUCT |
Object |
Cada campo STRUCT es una propiedad con nombre en el
tipo de datos Object . No se admite un campo STRUCT
sin nombre.
|
TIMESTAMP |
Date |
Date contiene un campo de microsegundos con la
fracción de microsegundos de TIMESTAMP .
|
Llama a una UDAF
En esta sección, se describen las diversas formas en las que puedes llamar a una UDAF persistente o temporal después de crearla en BigQuery.
Llama a una UDAF persistente
Puedes llamar a una UDAF persistente de la misma manera que llamas a una función de agregación integrada. Para obtener más información, consulta Llamadas a funciones de agregación. Debes incluir el conjunto de datos en la ruta de la función.
En el siguiente ejemplo, la consulta llama a una UDAF persistente que se llama WeightedAverage
:
SELECT my_project.my_dataset.WeightedAverage(item, weight, 2) AS weighted_average FROM ( SELECT 1 AS item, 2.45 AS weight UNION ALL SELECT 3 AS item, 0.11 AS weight UNION ALL SELECT 5 AS item, 7.02 AS weight );
Se genera una tabla con los siguientes resultados:
/*------------------*
| weighted_average |
+------------------+
| 4.5 |
*------------------*/
Llama a una UDAF temporal
Puedes llamar a una UDAF temporal de la misma manera en que llamas a una función de agregación integrada. Para obtener más información, consulta Llamadas a funciones de agregación.
La función temporal debe incluirse en una consulta de varias instrucciones o un procedimiento que contenga la llamada a la función de UDAF.
En el siguiente ejemplo, la consulta llama a una UDAF temporal que se llama WeightedAverage
:
CREATE TEMP AGGREGATE FUNCTION WeightedAverage(...) -- Temporary UDAF function call SELECT WeightedAverage(item, weight, 2) AS weighted_average FROM ( SELECT 1 AS item, 2.45 AS weight UNION ALL SELECT 3 AS item, 0.11 AS weight UNION ALL SELECT 5 AS item, 7.02 AS weight );
Se genera una tabla con los siguientes resultados:
/*------------------*
| weighted_average |
+------------------+
| 4.5 |
*------------------*/
Ignora o incluye filas con valores NULL
Cuando se llama a una UDAF de JavaScript con el argumento IGNORE NULLS
,
BigQuery omite automáticamente las filas para las que cualquier argumento
agregado se evalúa como NULL
. Estas filas se excluyen por completo
de la agregación y no se pasan a la función aggregate
de JavaScript. Cuando
se proporciona el argumento RESPECT NULLS
, se inhabilita el filtrado de NULL
y cada
fila se pasa a la UDAF de JavaScript, sin importar los valores NULL
.
Cuando no se proporcionan los argumentos IGNORE NULLS
ni RESPECT NULLS
, el
argumento predeterminado es IGNORE NULLS
.
En el siguiente ejemplo, se ilustran el comportamiento predeterminado NULL
,
el comportamiento IGNORE NULLS
y el comportamiento RESPECT NULLS
:
CREATE TEMP AGGREGATE FUNCTION SumPositive(x FLOAT64) RETURNS FLOAT64 LANGUAGE js AS r''' export function initialState() { return {sum: 0} } export function aggregate(state, x) { if (x == null) { // Use 1000 instead of 0 as placeholder for null so // that NULL values passed are visible in the result. state.sum += 1000; return; } if (x > 0) { state.sum += x; } } export function merge(state, partialState) { state.sum += partialState.sum; } export function finalize(state) { return state.sum; } '''; -- Call the JavaScript UDAF. WITH numbers AS ( SELECT * FROM UNNEST([1.0, 2.0, NULL]) AS x) SELECT SumPositive(x) AS sum, SumPositive(x IGNORE NULLS) AS sum_ignore_nulls, SumPositive(x RESPECT NULLS) AS sum_respect_nulls FROM numbers; /*-----+------------------+-------------------* | sum | sum_ignore_nulls | sum_respect_nulls | +-----+------------------+-------------------+ | 3.0 | 3.0 | 1003.0 | *-----+------------------+-------------------*/
Borra una UDAF
En esta sección, se describen las diversas formas en las que puedes borrar una UDAF persistente o temporal después de crearla en BigQuery.
Borra una UDAF persistente
Para borrar una UDAF, usa la declaración DROP FUNCTION
.
Debes incluir el conjunto de datos en la ruta de la función.
En el siguiente ejemplo, la consulta borra una UDAF persistente que se llama WeightedAverage
:
DROP FUNCTION IF EXISTS my_project.my_dataset.WeightedAverage;
Borra una UDAF temporal
Para borrar una UDAF temporal, usa la declaración DROP FUNCTION
.
En el siguiente ejemplo, la consulta borra una UDAF temporal que se llama WeightedAverage
:
DROP FUNCTION IF EXISTS WeightedAverage;
Una UDAF temporal vence apenas finaliza la consulta y no es necesario borrar la UDAF, a menos que desees quitarla antes de un procedimiento o una consulta de varias instrucciones.
Enumera UDAF
Las UDAF son un tipo de rutina. Para enumerar todas las rutinas en un conjunto de datos, consulta Enumera rutinas.
Sugerencias para un mejor rendimiento
Si deseas mejorar el rendimiento de tus consultas, ten en cuenta lo siguiente:
Realiza un filtro previo a tu entrada. El procesamiento de datos en JavaScript es más costoso que en SQL, por lo que es mejor filtrar la entrada tanto como sea posible en SQL primero.
La siguiente consulta es menos eficiente porque filtra la entrada a través de
x > 0
en la llamada a la UDAF:SELECT JsFunc(x) FROM t;
La siguiente consulta es más eficiente porque filtra previamente la entrada a través de
WHERE x > 0
antes de que se llame a la UDAF:SELECT JsFunc(x) FROM t WHERE x > 0;
Usa funciones de agregación integradas en lugar de JavaScript cuando sea posible. Volver a implementar una función de agregación integrada en JavaScript es más lento que llamar a una función de agregación integrada que hace lo mismo.
La siguiente consulta es menos eficiente porque implementa una UDAF:
SELECT SumSquare(x) FROM t;
La siguiente consulta es más eficiente porque implementa una función integrada que produce los mismos resultados que la consulta anterior:
SELECT SUM(x*x) FROM t;
Las UDAF de JavaScript son apropiadas para operaciones de agregación más complejas, que no se pueden expresar a través de funciones integradas.
Usa la memoria de manera eficaz. El entorno de procesamiento de JavaScript tiene memoria limitada disponible para cada consulta. Las consultas de UDAF de JavaScript que acumulan demasiado estado local pueden fallar debido al agotamiento de la memoria. Ten mucho cuidado con la minimización del tamaño de los objetos de estado de agregación y evita los estados de agregación que acumulan una gran cantidad de filas.
La siguiente consulta no es eficiente porque la función
aggregate
usa una cantidad de memoria no definida cuando la cantidad de filas procesadas es grande.export function initialState() { return {rows: []}; } export function aggregate(state, x) { state.rows.push(x); } ...
Usa tablas particionadas cuando sea posible. Por lo general, las UDAF de JavaScript se ejecutan de manera más eficiente cuando se realizan consultas en una tabla particionada en comparación con una tabla no particionada, ya que una tabla particionada almacena datos en muchos archivos más pequeños en comparación con una tabla no particionada, lo que permite un mayor paralelismo.
Limitaciones
Las UDAF tienen las mismas limitciones que se aplican a las UDF. Para obtener más detalles, consulta las limitaciones de UDF.
Solo los literales, los parámetros de consulta y las variables de secuencia de comandos se pueden pasar como argumentos no agregados para una UDAF.
No se admite el uso de la cláusula
ORDER BY
en una llamada a función UDAF de JavaScript.SELECT MyUdaf(x ORDER BY y) FROM t; -- Error: ORDER BY is unsupported.
Precios
Las UDAF se facturan según el modelo estándar de precios de BigQuery.
Cuotas y límites
Las UDAF tienen las mismas cuotas y los mismos límites que se aplican a las UDF. Para obtener información sobre las cuotas de UDF, consulta Cuotas y límites.