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 e finalize). 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 argumento state após a chamada da função aggregate ou merge 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ções serialize e deserialize 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ção partialState ao estado de agregação state. 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 final finalState.

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ção deserialize.

  • deserialize(serializedState): desserializa serializedState (anteriormente serializado pela função serialize) num estado de agregação que pode ser transmitido para as funções serialize, aggregate, merge ou finalize.

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.