Funções de agregação definidas pelo utilizador
Este documento descreve como criar, chamar e eliminar funções agregadas definidas pelo utilizador (UDAFs) no BigQuery.
Uma FUA permite-lhe criar uma função de agregação através de uma expressão que contém código. Uma FDAA aceita colunas de entrada, realiza um cálculo num grupo de linhas de cada vez e, em seguida, devolve o resultado desse cálculo como um único valor.
Crie uma UDAF SQL
Esta secção descreve as várias formas de criar uma UDAF SQL persistente ou temporária no BigQuery.
Crie uma UDAF SQL persistente
Pode criar uma UDAF SQL persistente, o que significa que pode reutilizar a UDAF em várias consultas. As FUAs persistentes são seguras para chamar quando são partilhadas entre proprietários. As UDAFs não podem alterar dados, comunicar com sistemas externos nem enviar registos para o Google Cloud Observability ou aplicações semelhantes.
Para criar uma UDAF persistente, use a
declaração CREATE AGGREGATE FUNCTION
sem a palavra-chave TEMP
ou TEMPORARY
. Tem de incluir o conjunto de dados no caminho da função.
Por exemplo, a seguinte consulta cria uma UDAF persistente denominada
ScaledAverage
:
CREATE AGGREGATE FUNCTION myproject.mydataset.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Crie uma UDAF SQL temporária
Pode criar uma UDAF SQL temporária, o que significa que a UDAF só existe no âmbito de uma única consulta, script, sessão ou procedimento.
Para criar uma FUDA temporária, use a declaração CREATE AGGREGATE FUNCTION
com a palavra-chave TEMP
ou TEMPORARY
.
Por exemplo, a seguinte consulta cria uma UDAF temporária denominada
ScaledAverage
:
CREATE TEMP AGGREGATE FUNCTION ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( AVG(dividend / divisor) );
Use parâmetros agregados e não agregados
Pode criar uma UDAF SQL que tenha parâmetros agregados e não agregados.
Normalmente, as FUAs agregam parâmetros de funções em todas as linhas num grupo.
No entanto, pode especificar um parâmetro de função como não agregado com a palavra-chave NOT AGGREGATE
.
Um parâmetro de função não agregada é um parâmetro de função escalar com um valor constante para todas as linhas num grupo. Um parâmetro de função não agregada válido tem de ser um literal. Na definição da UDAF, os parâmetros da função de agregação só podem aparecer como argumentos da função para chamadas da função de agregação. As referências a parâmetros de funções não agregadas podem aparecer em qualquer lugar na definição da UDAF.
Por exemplo, a seguinte função contém um parâmetro agregado denominado dividend
e um parâmetro não agregado denominado divisor
:
-- Create the function. CREATE TEMP AGGREGATE FUNCTION ScaledSum( dividend FLOAT64, divisor FLOAT64 NOT AGGREGATE) RETURNS FLOAT64 AS ( SUM(dividend) / divisor );
Use o projeto predefinido no corpo da função
No corpo de uma UDAF SQL, todas as referências a entidades do BigQuery, como tabelas ou vistas, têm de incluir o ID do projeto, a menos que a entidade resida no mesmo projeto que contém a UDAF.
Por exemplo, considere a seguinte declaração:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM dataset_a.my_table ) );
Se executar a declaração anterior no projeto project1
, a declaração é bem-sucedida porque my_table
existe em project1
. No entanto, se executar a declaração anterior a partir de um projeto diferente, a declaração falha.
Para corrigir o erro, inclua o ID do projeto na referência da tabela:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM project1.dataset_a.my_table ) );
Também pode fazer referência a uma entidade num projeto ou conjunto de dados diferente daquele em que cria a função:
CREATE AGGREGATE FUNCTION project1.dataset_a.ScaledAverage( dividend FLOAT64, divisor FLOAT64) RETURNS FLOAT64 AS ( ( SELECT AVG(dividend / divisor) FROM project2.dataset_c.my_table ) );
Crie uma UDAF JavaScript
Esta secção descreve as várias formas de criar uma UDAF JavaScript no BigQuery. Existem algumas regras a observar ao criar uma UDAF JavaScript:
O corpo da UDAF JavaScript tem de ser um literal de string entre aspas que representa o código JavaScript. Para saber mais sobre os diferentes tipos de literais de strings entre aspas que pode usar, consulte o artigo Formatos para literais entre aspas.
Apenas são permitidas determinadas codificações de tipo. Para mais informações, consulte o artigo Codificações de tipos SQL permitidas numa UDAF JavaScript.
O corpo da função JavaScript tem de incluir quatro funções JavaScript que inicializam, agregam, unem e finalizam os resultados para a UDAF JavaScript (
initialState
,aggregate
,merge
efinalize
). Para mais informações, consulte o artigo Codificações de tipos SQL permitidas numa UDAF JavaScript.Qualquer valor devolvido pela função
initialState
ou que seja deixado no argumentostate
após a chamada da funçãoaggregate
oumerge
tem de ser serializável. Se quiser trabalhar com dados de agregação não serializáveis, como funções ou campos de símbolos, tem de usar as funçõesserialize
edeserialize
incluídas. Para saber mais, consulte o artigo Serializar e desserializar dados numa UDAF JavaScript.
Crie uma UDAF de JavaScript persistente
Pode criar uma UDAF JavaScript persistente, o que significa que pode reutilizar a UDAF em várias consultas. As FUAs persistentes são seguras para chamar quando são partilhadas entre proprietários. As UDAFs não podem alterar dados, comunicar com sistemas externos nem enviar registos para o Google Cloud Observability ou aplicações semelhantes.
Para criar uma UDAF persistente, use a
declaração CREATE AGGREGATE FUNCTION
sem a palavra-chave
TEMP
ou TEMPORARY
. Tem de incluir o conjunto de dados no caminho da função.
A consulta seguinte cria uma UDAF JavaScript persistente denominada
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 | *-----*/
Crie uma UDAF de JavaScript temporária
Pode criar uma FUAJ temporária, o que significa que a FUAJ só existe no âmbito de uma única consulta, script, sessão ou procedimento.
Para criar uma FUDA temporária, use a declaração CREATE AGGREGATE FUNCTION
com a palavra-chave TEMP
ou TEMPORARY
.
A seguinte consulta cria uma UDAF JavaScript temporária denominada
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 | *-----*/
Inclua parâmetros não agregados numa UDAF JavaScript
Pode criar uma UDAF JavaScript que tenha parâmetros agregados e não agregados.
Normalmente, as FUAs agregam parâmetros de funções em todas as linhas num grupo.
No entanto, pode especificar um parâmetro de função como não agregado com a palavra-chave NOT AGGREGATE
.
Um parâmetro de função não agregada é um parâmetro de função escalar com um valor constante para todas as linhas num grupo. Um parâmetro de função não agregada válido tem de ser um literal. Na definição da UDAF, os parâmetros da função de agregação só podem aparecer como argumentos da função para chamadas da função de agregação. As referências a parâmetros de funções não agregadas podem aparecer em qualquer lugar na definição da UDAF.
No exemplo seguinte, a UDAF JavaScript contém um parâmetro
agregado denominado s
e um parâmetro não agregado denominado 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 e desserializar dados numa UDAF JavaScript
O BigQuery tem de serializar qualquer objeto devolvido pela função initialState
ou que seja deixado no argumento state
após a chamada da função aggregate
ou merge
.
O BigQuery suporta a serialização de um objeto se todos os campos forem um dos seguintes:
- Um valor primitivo de JavaScript (por exemplo:
2
,"abc"
,null
,undefined
). - Um objeto JavaScript para o qual o BigQuery suporta a serialização de todos os valores dos campos.
- Uma matriz JavaScript para a qual o BigQuery suporta a serialização de todos os elementos.
Os seguintes valores de retorno são serializáveis:
export function initialState() {
return {a: "", b: 3, c: null, d: {x: 23} }
}
export function initialState() {
return {value: 2.3};
}
Os seguintes valores de retorno não são serializáveis:
export function initialState() {
return {
value: function() {return 6;}
}
}
export function initialState() {
return 2.3;
}
Se quiser trabalhar com estados de agregação não serializáveis, a UDAF de JavaScript tem de incluir as funções serialize
e deserialize
.
A função serialize
converte o estado de agregação num objeto serializável; a função deserialize
converte o objeto serializável novamente num estado de agregação.
No exemplo seguinte, uma biblioteca externa calcula somas através de uma interface:
export class SumAggregator { constructor() { this.sum = 0; } update(value) { this.sum += value; } getSum() { return this.sum; } }
A consulta seguinte não é executada porque o objeto de classe SumAggregator
não é serializável no BigQuery devido à presença de funções na classe.
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;
Se adicionar as funções serialize
e deserialize
à consulta anterior,
a consulta é executada porque o objeto de classe SumAggregator
é convertido num
objeto serializável do BigQuery e, em seguida, novamente num
objeto de classe 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 saber mais sobre as funções de serialização, consulte o artigo Funções de serialização de JavaScript opcionais.
Inclua variáveis globais e funções personalizadas numa UDAF JavaScript
O corpo da função JavaScript pode incluir código JavaScript personalizado, como variáveis globais de JavaScript e funções personalizadas.
As variáveis globais são executadas quando o JavaScript é carregado
no BigQuery e antes de a função initialState
ser executada.
As variáveis globais podem ser úteis se precisar de realizar um trabalho de inicialização único que não deve ser repetido para cada grupo de agregação, como seria o caso com as funções initialState
, aggregate
, merge
e finalize
.
Não use variáveis globais para armazenar o estado de agregação. Em alternativa, limite o estado de agregação aos objetos transmitidos às funções exportadas. Use apenas variáveis globais para colocar em cache operações dispendiosas que não sejam específicas de nenhuma operação de agregação em particular.
Na consulta seguinte, a função SumOfPrimes
calcula uma soma, mas apenas os números primos são incluídos no cálculo. No corpo da função JavaScript, existem duas variáveis globais, primes
e maxTested
, que são inicializadas primeiro. Além disso, existe uma função personalizada denominada isPrime
que verifica se um número é 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 | *-----*/
Inclua bibliotecas JavaScript
Pode expandir as UDAFs JavaScript com a opção library
na cláusula OPTIONS
. Esta opção permite-lhe especificar bibliotecas de código externas para a UDAF JavaScript e, em seguida, importar essas bibliotecas com a declaração import
.
No exemplo seguinte, o código em bar.js
está disponível para qualquer código no corpo da função da UDAF 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 ...; } ''';
Estrutura de JavaScript necessária
Ao contrário de uma FDU de JavaScript, em que o corpo da função é JavaScript de forma livre que é executado para cada linha, o corpo da função para uma FDUA de JavaScript é um módulo de JavaScript que contém algumas funções exportadas incorporadas, que são invocadas em várias fases do processo de agregação. Algumas destas funções incorporadas são obrigatórias, enquanto outras são opcionais. Também pode adicionar as suas funções JavaScript.
Funções de agregação JavaScript obrigatórias
Pode incluir as suas funções JavaScript, mas o corpo da função JavaScript tem de incluir as seguintes funções JavaScript exportáveis:
initialState([nonAggregateParam])
: devolve um objeto JavaScript que representa um estado de agregação no qual ainda não foram agregadas linhas.aggregate(state, aggregateParam[, ...][, nonAggregateParam])
: agrega uma linha de dados, atualizando o estado para armazenar o resultado da agregação. Não devolve um valor.merge(state, partialState, [nonAggregateParam])
: junta o estado de agregaçãopartialState
ao estado de agregaçãostate
. Esta função é usada quando o motor agrega diferentes secções de dados em paralelo e precisa de combinar os resultados. Não devolve um valor.finalize(finalState, [nonAggregateParam])
: devolve o resultado final da função de agregação, dado um estado de agregação finalfinalState
.
Para saber mais sobre as funções necessárias, consulte o artigo Funções necessárias numa UDAF JavaScript.
Funções de serialização JavaScript opcionais
Se quiser trabalhar com estados de agregação não serializáveis, a UDAF JavaScript tem de fornecer as funções serialize
e deserialize
.
A função serialize
converte o estado de agregação num objeto serializável do BigQuery; a função deserialize
converte o objeto serializável do BigQuery novamente num estado de agregação.
serialize(state)
: devolve um objeto serializável que contém as informações no estado de agregação, a serem desserializadas através da funçãodeserialize
.deserialize(serializedState)
: desserializaserializedState
(anteriormente serializado pela funçãoserialize
) num estado de agregação que pode ser transmitido para as funçõesserialize
,aggregate
,merge
oufinalize
.
Para saber mais acerca das funções de serialização JavaScript incorporadas, consulte o artigo Funções de serialização para uma FADU JavaScript.
Para saber como serializar e desserializar dados com uma UDAF JavaScript, consulte o artigo Serializar e desserializar dados numa UDAF JavaScript.
Codificações de tipo SQL permitidas numa FDUA JavaScript
Nas FUAs JavaScript, os seguintes tipos de dados GoogleSQL suportados representam os tipos de dados JavaScript da seguinte forma:
Tipo de dados do GoogleSQL |
Tipo de dados de JavaScript |
Notas |
---|---|---|
ARRAY |
Array |
Não é suportada uma matriz de matrizes. Para contornar esta limitação, use os tipos de dados Array<Object<Array>> (JavaScript) e ARRAY<STRUCT<ARRAY>> (GoogleSQL).
|
BIGNUMERIC
|
Number ou String
|
Igual a NUMERIC .
|
BOOL |
Boolean |
|
BYTES |
Uint8Array |
|
DATE |
Date |
|
FLOAT64 |
Number |
|
INT64 |
BigInt |
|
JSON |
Vários tipos |
O tipo de dados JSON do GoogleSQL pode ser convertido
num Object , Array ou outro tipo de dados JavaScript
compatível com o GoogleSQL.
|
NUMERIC
|
Number ou String
|
Se um valor NUMERIC puder ser representado exatamente como um valor de vírgula flutuante IEEE 754 (intervalo [-253, 253] ) e não tiver parte fracionária, é codificado como um tipo de dados Number . Caso contrário, é codificado como um tipo de dados String .
|
STRING |
String |
|
STRUCT |
Object |
Cada campo STRUCT é uma propriedade com nome no tipo de dados Object . Um campo STRUCT sem nome não é suportado.
|
TIMESTAMP |
Date |
Date contém um campo de microssegundos com a fração de microssegundos de TIMESTAMP .
|
Chamar uma UDAF
Esta secção descreve as várias formas de chamar uma UDAF persistente ou temporária depois de a criar no BigQuery.
Chame uma FUA persistente
Pode chamar uma UDAF persistente da mesma forma que chama uma função de agregação integrada. Para mais informações, consulte o artigo Agregue chamadas de funções. Tem de incluir o conjunto de dados no caminho da função.
No exemplo seguinte, a consulta chama uma UDAF persistente com o nome 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 );
É produzida uma tabela com os seguintes resultados:
/*------------------*
| weighted_average |
+------------------+
| 4.5 |
*------------------*/
Chame uma FUA agregada temporária
Pode chamar uma UDAF temporária da mesma forma que chama uma função de agregação integrada. Para mais informações, consulte o artigo Agregue chamadas de funções.
A função temporária tem de ser incluída numa consulta com várias declarações ou num procedimento que contenha a chamada da função UDAF.
No exemplo seguinte, a consulta chama uma UDAF temporária com o nome 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 );
É produzida uma tabela com os seguintes resultados:
/*------------------*
| weighted_average |
+------------------+
| 4.5 |
*------------------*/
Ignorar ou incluir linhas com valores NULL
Quando uma UDAF JavaScript é chamada com o argumento IGNORE NULLS
, o BigQuery ignora automaticamente as linhas para as quais qualquer argumento agregado é avaliado como NULL
. Essas linhas são excluídas completamente da agregação e não são transmitidas para a função JavaScript aggregate
. Quando o argumento RESPECT NULLS
é fornecido, a filtragem NULL
é desativada e todas as linhas são transmitidas para a UDAF JavaScript, independentemente dos valores NULL
.
Quando não é fornecido o argumento IGNORE NULLS
nem o argumento RESPECT NULLS
, o argumento predefinido é IGNORE NULLS
.
O exemplo seguinte ilustra o comportamento NULL
predefinido, o comportamento IGNORE NULLS
e o comportamento 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 | *-----+------------------+-------------------*/
Elimine uma UDAF
Esta secção descreve as várias formas de eliminar uma UDAF persistente ou temporária depois de a ter criado no BigQuery.
Elimine uma FUA persistente
Para eliminar uma UDAF persistente, use a declaração
DROP FUNCTION
.
Tem de incluir o conjunto de dados no caminho da função.
No exemplo seguinte, a consulta elimina uma UDAF persistente com o nome
WeightedAverage
:
DROP FUNCTION IF EXISTS my_project.my_dataset.WeightedAverage;
Elimine uma UDAF temporária
Para eliminar uma UDAF temporária, use a declaração DROP FUNCTION
.
No exemplo seguinte, a consulta elimina uma UDAF temporária com o nome WeightedAverage
:
DROP FUNCTION IF EXISTS WeightedAverage;
Uma FDAU temporária expira assim que a consulta terminar. Não é necessário eliminar a UDAF, a menos que a queira remover antecipadamente de uma consulta com várias declarações ou de um procedimento.
Liste UDAFs
As FUAs são um tipo de rotina. Para listar todas as rotinas num conjunto de dados, consulte Listar rotinas.
Sugestões de desempenho
Se quiser melhorar o desempenho das suas consultas, considere o seguinte:
Pré-filtre a sua introdução. O processamento de dados em JavaScript é mais caro do que em SQL, pelo que é melhor filtrar a entrada o máximo possível primeiro em SQL.
A seguinte consulta é menos eficiente porque filtra a entrada através de
x > 0
na chamada UDAF:SELECT JsFunc(x) FROM t;
A seguinte consulta é mais eficiente porque pré-filtra a entrada usando
WHERE x > 0
antes de a UDAF ser chamada:SELECT JsFunc(x) FROM t WHERE x > 0;
Sempre que possível, use funções de agregação integradas em vez de JavaScript. A reimplementação de uma função de agregação integrada em JavaScript é mais lenta do que chamar uma função de agregação integrada que faz a mesma coisa.
A seguinte consulta é menos eficiente porque implementa uma UDAF:
SELECT SumSquare(x) FROM t;
A seguinte consulta é mais eficiente porque implementa uma função integrada que produz os mesmos resultados que a consulta anterior:
SELECT SUM(x*x) FROM t;
As FUAs JavaScript são adequadas para operações de agregação mais complexas, que não podem ser expressas através de funções integradas.
Use a memória de forma eficiente. O ambiente de processamento JavaScript tem memória limitada disponível para cada consulta. As consultas UDAF JavaScript que acumulam demasiado estado local podem falhar devido ao esgotamento da memória. Tenha especial atenção à minimização do tamanho dos objetos de estado de agregação e evite estados de agregação que acumulam um grande número de linhas.
A consulta seguinte não é eficiente porque a função
aggregate
usa uma quantidade ilimitada de memória quando o número de linhas processadas aumenta.export function initialState() { return {rows: []}; } export function aggregate(state, x) { state.rows.push(x); } ...
Use tabelas particionadas sempre que possível. Normalmente, as FUAs JavaScript são executadas de forma mais eficiente quando são consultadas numa tabela particionada em comparação com uma tabela não particionada, porque uma tabela particionada armazena dados em muitos ficheiros mais pequenos em comparação com uma tabela não particionada, o que permite um paralelismo mais elevado.
Limitações
As UDAFs têm as mesmas limitações que se aplicam às UDFs. Para ver detalhes, consulte as limitações das FDU.
Só é possível transmitir literais, parâmetros de consulta e variáveis de script como argumentos não agregados para uma UDAF.
A utilização da cláusula
ORDER BY
numa chamada de função UDAF JavaScript não é suportada.SELECT MyUdaf(x ORDER BY y) FROM t; -- Error: ORDER BY is unsupported.
Preços
As FUAs são faturadas através do modelo de preços do BigQuery padrão.
Quotas e limites
As FUAs têm as mesmas quotas e limites que se aplicam às FUs. Para obter informações sobre as quotas de FDU, consulte o artigo Quotas e limites.