Funciones de agregación definidas por el usuario
En este documento se describe cómo crear, llamar y eliminar funciones de agregación definidas por el usuario (UDAFs) en BigQuery.
Las funciones de agregación definidas por el usuario te permiten crear una función de agregación mediante una expresión que contiene código. Una FUDA acepta columnas de entrada, realiza un cálculo en un grupo de filas a la vez y, a continuación, devuelve el resultado de ese cálculo como un solo valor.
Crear una UDAF de SQL
En esta sección se describen las distintas formas de crear una UDAF de SQL persistente o temporal en BigQuery.
Crear una UDAF de SQL persistente
Puedes crear una UDAF de SQL persistente, lo que significa que puedes reutilizarla en varias consultas. Las UDAFs persistentes se pueden llamar de forma segura cuando se comparten entre propietarios. Las UDAFs no pueden modificar datos, comunicarse con sistemas externos ni enviar registros a Google Cloud Observability u otras aplicaciones similares.
Para crear una UDAF persistente, usa la declaración CREATE AGGREGATE FUNCTION
sin las palabras clave TEMP
ni TEMPORARY
. Debe incluir el conjunto de datos en la ruta de la función.
Por ejemplo, la siguiente consulta crea una UDAF persistente llamada ScaledAverage
:
CREATE AGGREGATE FUNCTION myproject.mydataset.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Crear una UDAF de SQL temporal
Puedes crear una UDAF de SQL temporal, lo que significa que la UDAF solo existe en el ámbito de una consulta, un script, una sesión o un procedimiento.
Para crear una UDAF temporal, usa la
instrucción CREATE AGGREGATE FUNCTION
con la palabra clave TEMP
o TEMPORARY
.
Por ejemplo, la siguiente consulta crea una UDAF temporal llamada ScaledAverage
:
CREATE TEMP AGGREGATE FUNCTION ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Usar parámetros agregados y no agregados
Puede crear una UDAF de SQL que tenga parámetros agregados y no agregados.
Las UDAFs suelen agregar 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 no agregada 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 no agregada válido debe ser un literal. Dentro de la definición de la UDAF, los parámetros de la función de agregación solo pueden aparecer como argumentos de función en las llamadas a la función de agregación. 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 de agregación llamado dividend
y un parámetro que no es de agregación llamado divisor
:
-- Create the function. CREATE TEMP AGGREGATE FUNCTION ScaledSum( dividend FLOAT64, divisor FLOAT64 NOT AGGREGATE) RETURNS FLOAT64 AS ( SUM(dividend) / divisor );
Usar 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 se encuentre en el mismo proyecto que contiene la UDAF.
Por ejemplo, considera la siguiente afirmació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 instrucción se completará correctamente porque my_table
existe en project1
. Sin embargo, si ejecutas la instrucción anterior desde otro proyecto, la instrucción fallará.
Para corregir el error, incluya 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 de otro proyecto o conjunto de datos distinto de aquel en el que creas 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 ) );
Crear una UDAF de JavaScript
En esta sección se describen las distintas formas de crear una FDU de JavaScript en BigQuery. Hay algunas reglas que debes seguir al crear una UDAF de JavaScript:
El cuerpo de la UDAF de JavaScript debe ser un literal de cadena entre comillas que represente el código JavaScript. Para obtener más información sobre los distintos tipos de literales de cadena entre comillas que puede usar, consulte Formatos de literales entre comillas.
Solo se permiten determinados tipos de codificación. Para obtener más información, consulta Codificaciones de tipos de SQL permitidas en una UDAF de JavaScript.
El cuerpo de la función JavaScript debe incluir cuatro funciones JavaScript que inicialicen, agreguen, combinen y finalicen los resultados de la función de agregación definida por el usuario (UDAF) de JavaScript (
initialState
,aggregate
,merge
yfinalize
). Para obtener más información, consulte Codificaciones de tipos de SQL permitidas en una UDAF de JavaScript.Cualquier valor devuelto por la función
initialState
o que quede en el argumentostate
después de llamar a la funciónaggregate
omerge
debe poder serializarse. Si quieres 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 Serializar y deserializar datos en una UDAF de JavaScript.
Crear una UDAF de JavaScript persistente
Puedes crear una UDAF de JavaScript persistente, lo que significa que puedes reutilizarla en varias consultas. Las UDAFs persistentes se pueden llamar de forma segura cuando se comparten entre propietarios. Las UDAFs no pueden modificar datos, comunicarse con sistemas externos ni enviar registros a Google Cloud Observability u otras aplicaciones similares.
Para crear una UDAF persistente, usa la declaración CREATE AGGREGATE FUNCTION
sin las palabras clave TEMP
ni TEMPORARY
. Debe incluir el conjunto de datos en la ruta de la función.
La siguiente consulta crea una UDAF de JavaScript persistente llamada 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 | *-----*/
Crear una UDAF de JavaScript temporal
Puedes crear una UDAF de JavaScript temporal, lo que significa que la UDAF solo existe en el ámbito de una consulta, un script, una sesión o un procedimiento.
Para crear una UDAF temporal, usa la
instrucción CREATE AGGREGATE FUNCTION
con la palabra clave TEMP
o TEMPORARY
.
La siguiente consulta crea una UDAF temporal de JavaScript llamada 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 | *-----*/
Incluir parámetros no agregados en una UDAF de JavaScript
Puedes crear una UDAF de JavaScript que tenga parámetros agregados y no agregados.
Las UDAFs suelen agregar 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 no agregada 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 no agregada válido debe ser un literal. Dentro de la definición de la UDAF, los parámetros de la función de agregación solo pueden aparecer como argumentos de función en las llamadas a la función de agregación. Las referencias a parámetros de funciones no agregadas pueden aparecer en cualquier parte de la definición de la UDAF.
En el ejemplo siguiente, 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 | *-----------------*/
Serializar y deserializar datos en una UDAF de JavaScript
BigQuery debe serializar cualquier objeto devuelto por la función initialState
o que quede en el argumento state
después de llamar a la función aggregate
o merge
.
BigQuery admite la serialización de un objeto si todos los campos son de uno de los siguientes tipos:
- Un valor primitivo de JavaScript (por ejemplo,
2
,"abc"
,null
oundefined
). - Objeto JavaScript para el que BigQuery admite la serialización de todos los valores de los campos.
- Una matriz de JavaScript para la que BigQuery admite la serialización de todos los elementos.
Los siguientes valores devueltos se pueden serializar:
export function initialState() {
return {a: "", b: 3, c: null, d: {x: 23} }
}
export function initialState() {
return {value: 2.3};
}
Los siguientes valores devueltos no se pueden serializar:
export function initialState() {
return {
value: function() {return 6;}
}
}
export function initialState() {
return 2.3;
}
Si quieres 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, mientras que la función deserialize
convierte el objeto serializable en un estado de agregación.
En el siguiente ejemplo, una biblioteca externa calcula sumas mediante 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 en 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 añades las funciones serialize
y deserialize
a la consulta anterior, la consulta se ejecutará porque el objeto de clase SumAggregator
se convierte en un objeto que se puede serializar en BigQuery y, después, vuelve a ser 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 sobre las funciones de serialización, consulta Funciones de serialización de JavaScript opcionales.
Incluir variables globales y funciones personalizadas en una UDAF de JavaScript
El cuerpo de la función JavaScript puede incluir código JavaScript personalizado, como variables globales de JavaScript y funciones personalizadas.
Las variables globales se ejecutan cuando se carga el código JavaScript en BigQuery y antes de que se ejecute la función initialState
.
Las variables globales pueden ser útiles si necesitas realizar una inicialización única que no se repita en cada grupo de agregación, como ocurre 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 transfieren a las funciones exportadas. Usa solo variables globales para almacenar en caché operaciones costosas que no sean específicas de ninguna operación de agregación en concreto.
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 JavaScript, hay dos variables globales, primes
y maxTested
, que se inicializan primero. Además, hay una función personalizada llamada isPrime
que comprueba 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 | *-----*/
Incluir bibliotecas de JavaScript
Puedes ampliar tus UDAFs 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, a continuación, importar esas bibliotecas con la declaración import
.
En el ejemplo siguiente, el código de bar.js
está disponible para cualquier código del 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 función definida por el usuario de JavaScript, en la que el cuerpo de la función es JavaScript de formato libre que se ejecuta en cada fila, el cuerpo de la función de una función de agregación definida por el usuario de JavaScript es un módulo de JavaScript que contiene algunas funciones exportadas integradas, que se invocan en varias fases del proceso de agregación. Algunas de estas funciones integradas son obligatorias, mientras que otras son opcionales. También puedes añadir tus funciones de JavaScript.
Funciones de agregación de JavaScript obligatorias
Puedes incluir tus funciones de JavaScript, pero el cuerpo de la función de JavaScript debe incluir las siguientes funciones de JavaScript exportables:
initialState([nonAggregateParam])
: devuelve un objeto JavaScript que representa un estado de agregación en el que aún no se han agregado filas.aggregate(state, aggregateParam[, ...][, nonAggregateParam])
: agrega una fila de datos y actualiza el estado para almacenar el resultado de la agregación. No devuelve ningún valor.merge(state, partialState, [nonAggregateParam])
: combina el estado de agregaciónpartialState
con 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 devuelve ningún valor.finalize(finalState, [nonAggregateParam])
: devuelve el resultado final de la función de agregación, dado un estado de agregación finalfinalState
.
Para obtener más información sobre las funciones obligatorias, consulta Funciones obligatorias en una función agregada definida por el usuario de JavaScript.
Funciones de serialización de JavaScript opcionales
Si quieres 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 serializable de BigQuery, mientras que la función deserialize
convierte el objeto serializable de BigQuery en un estado de agregación.
serialize(state)
: devuelve un objeto serializable que contiene la información del estado de agregación. Se deserializa mediante la funcióndeserialize
.deserialize(serializedState)
: deserializaserializedState
(anteriormente serializado por la funciónserialize
) en un estado de agregación que se puede transferir a las funcionesserialize
,aggregate
,merge
ofinalize
.
Para obtener más información sobre las funciones de serialización de JavaScript integradas, consulta Funciones de serialización de una función de agregación definida por el usuario de JavaScript.
Para saber cómo serializar y deserializar datos con una UDAF de JavaScript, consulta Serializar y deserializar datos en una UDAF de JavaScript.
Codificaciones de tipos de SQL permitidas en una FDUA de JavaScript
En las UDAFs de JavaScript, los siguientes tipos de datos de GoogleSQL admitidos representan tipos de datos de JavaScript de la siguiente manera:
Tipo de datos de GoogleSQL |
Tipo de datos JavaScript |
Notas |
---|---|---|
ARRAY |
Array |
No se admiten matrices de matrices. 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 Object , Array u otro tipo de datos de JavaScript compatible con GoogleSQL.
|
NUMERIC
|
Number o String
|
Si un valor NUMERIC se puede representar exactamente como un valor de coma flotante IEEE 754 (intervalo [-253, 253] ) y no tiene 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 del 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 .
|
Llamar a una UDAF
En esta sección se describen las distintas formas de llamar a una FDUA persistente o temporal después de crearla en BigQuery.
Llamar a una FUDA persistente
Puedes llamar a una UDAF persistente de la misma forma que llamas a una función de agregado integrada. Para obtener más información, consulta Agrega llamadas a funciones. Debe incluir el conjunto de datos en la ruta de la función.
En el ejemplo siguiente, la consulta llama a una UDAF persistente denominada 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 |
*------------------*/
Llamar a una UDAF temporal
Puedes llamar a una UDAF temporal de la misma forma que llamas a una función de agregado integrada. Para obtener más información, consulta Agrega llamadas a funciones.
La función temporal debe incluirse en una consulta de varias instrucciones o en un procedimiento que contenga la llamada a la función de agregación definida por el usuario.
En el siguiente ejemplo, la consulta llama a una UDAF temporal llamada 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 |
*------------------*/
Ignorar o incluir filas con valores NULL
Cuando se llama a una UDAF de JavaScript con el argumento IGNORE NULLS
, BigQuery omite automáticamente las filas en las que cualquier argumento agregado se evalúa como NULL
. Estas filas se excluyen por completo de la agregación y no se transfieren a la función aggregate
de JavaScript. Si se proporciona el argumento RESPECT NULLS
, se inhabilita el filtrado de NULL
y cada fila se transfiere a la UDAF de JavaScript, independientemente de los valores de NULL
.
Si no se proporciona el argumento IGNORE NULLS
ni el RESPECT NULLS
, el argumento predeterminado es IGNORE NULLS
.
En el siguiente ejemplo se ilustra el comportamiento predeterminado de NULL
, el comportamiento de IGNORE NULLS
y el comportamiento de 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 | *-----+------------------+-------------------*/
Eliminar una UDAF
En esta sección se describen las distintas formas de eliminar una FDUA persistente o temporal después de haberla creado en BigQuery.
Eliminar una UDAF persistente
Para eliminar una UDAF persistente, usa la instrucción DROP FUNCTION
.
Debe incluir el conjunto de datos en la ruta de la función.
En el ejemplo siguiente, la consulta elimina una UDAF persistente llamada WeightedAverage
:
DROP FUNCTION IF EXISTS my_project.my_dataset.WeightedAverage;
Eliminar una UDAF temporal
Para eliminar una UDAF temporal, usa la instrucción DROP FUNCTION
.
En el ejemplo siguiente, la consulta elimina una UDAF temporal llamada WeightedAverage
:
DROP FUNCTION IF EXISTS WeightedAverage;
Las UDAFs temporales caducan en cuanto finaliza la consulta. No es necesario eliminar la función agregada definida por el usuario, a menos que quieras quitarla antes de tiempo de una consulta con varias instrucciones o de un procedimiento.
Mostrar UDAFs
Las UDAFs son un tipo de rutina. Para enumerar todas las rutinas de un conjunto de datos, consulta Listar rutinas.
Consejos sobre rendimiento
Si quieres mejorar el rendimiento de tus consultas, ten en cuenta lo siguiente:
Prefiltra la entrada. Procesar datos en JavaScript es más caro que en SQL, por lo que es mejor filtrar la entrada lo máximo posible en SQL primero.
La siguiente consulta es menos eficiente porque filtra la entrada mediante
x > 0
en la llamada a la UDAF:SELECT JsFunc(x) FROM t;
La siguiente consulta es más eficiente porque prefiltra la entrada mediante
WHERE x > 0
antes de llamar a la UDAF:SELECT JsFunc(x) FROM t WHERE x > 0;
Usa funciones de agregación integradas en lugar de JavaScript siempre que 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 haga 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 UDAFs de JavaScript son adecuadas para operaciones de agregación más complejas que no se pueden expresar mediante funciones integradas.
Usar la memoria de forma eficiente. El entorno de procesamiento de JavaScript tiene una cantidad limitada de memoria disponible para cada consulta. Las consultas de UDAF de JavaScript que acumulan demasiado estado local pueden fallar debido al agotamiento de la memoria. Presta especial atención a la hora de minimizar el tamaño de los objetos de estado de agregación y evita los estados de agregación que acumulen un gran número de filas.
La siguiente consulta no es eficiente porque la función
aggregate
usa una cantidad de memoria ilimitada cuando el número de filas procesadas es grande.export function initialState() { return {rows: []}; } export function aggregate(state, x) { state.rows.push(x); } ...
Utiliza tablas con particiones siempre que sea posible. Las UDAFs de JavaScript suelen ejecutarse de forma más eficiente cuando se consultan tablas con particiones que tablas sin particiones, ya que las tablas con particiones almacenan los datos en muchos archivos más pequeños que las tablas sin particiones, lo que permite un mayor paralelismo.
Limitaciones
Las UDAFs tienen las mismas limitaciones que las UDFs. Para obtener más información, consulta Limitaciones de las UDFs.
Solo se pueden transferir literales, parámetros de consulta y variables de secuencias de comandos como argumentos no agregados de una UDAF.
No se admite el uso de la cláusula
ORDER BY
en una llamada a una función de agregación definida por el usuario (UDAF) de JavaScript.SELECT MyUdaf(x ORDER BY y) FROM t; -- Error: ORDER BY is unsupported.
Precios
Las UDAFs se facturan con el modelo de precios de BigQuery estándar.
Cuotas y límites
Las UDAFs tienen las mismas cuotas y límites que las UDFs. Para obtener información sobre las cuotas de las UDFs, consulta Cuotas y límites.