Práticas recomendadas para funções
Neste documento, descrevemos como otimizar consultas que usam funções SQL.
Comparação de strings do Optimize
Prática recomendada: quando possível, use LIKE
em vez de REGEXP_CONTAINS
.
No BigQuery, é possível usar a função
REGEXP_CONTAINS
ou o operador LIKE
para comparar strings. REGEXP_CONTAINS
fornece mais funcionalidades,
mas também tem um tempo de execução mais lento. O uso de LIKE
em vez de REGEXP_CONTAINS
é mais rápido, especialmente se você não precisar de todo o poder das expressões regulares
fornecidas por REGEXP_CONTAINS
, como a correspondência de caracteres curinga.
Considere o seguinte uso da função REGEXP_CONTAINS
:
SELECT dim1 FROM `dataset.table1` WHERE REGEXP_CONTAINS(dim1, '.*test.*');
É possível otimizar essa consulta da seguinte maneira:
SELECT dim1 FROM `dataset.table` WHERE dim1 LIKE '%test%';
Otimizar funções de agregação
Prática recomendada: se for compatível com o caso de uso, use uma função de agregação aproximada.
Se a função de agregação SQL que você está usando tiver uma função de aproximação
equivalente, a função de aproximação produzirá um desempenho de consulta mais rápido. Por
exemplo, em vez de usar COUNT(DISTINCT)
, use APPROX_COUNT_DISTINCT
.
Para mais informações, consulte
funções de agregação aproximadas.
Você também pode usar funções HyperLogLog++
para fazer aproximações, incluindo agregações
aproximadas personalizadas. Para mais informações, consulte as
funções HyperLogLog++
na referência do GoogleSQL.
Considere o seguinte uso da função COUNT
:
SELECT dim1, COUNT(DISTINCT dim2) FROM `dataset.table` GROUP BY 1;
É possível otimizar essa consulta da seguinte maneira:
SELECT dim1, APPROX_COUNT_DISTINCT(dim2) FROM `dataset.table` GROUP BY 1;
Otimizar funções de quantil
Prática recomendada: quando possível, use APPROX_QUANTILE
em vez de NTILE
.
Uma consulta que contém a função
NTILE
pode falhar com um erro
Resources exceeded
se também houver muitos elementos para ORDER BY
em uma única partição, o que faz com que o volume de dados aumente.
A janela analítica não é particionada, portanto, a computação NTILE
requer
um ORDER BY
global para que todas as linhas na tabela sejam processadas
por um único worker/slot.
Tente usar
APPROX_QUANTILES
. Essa função permite que a consulta seja executada com mais eficiência, porque não requer um ORDER BY
global para todas as linhas na tabela.
Considere o seguinte uso da função NTILE
:
SELECT individual_id, NTILE(nbuckets) OVER (ORDER BY sales desc) AS sales_third FROM `dataset.table`;
É possível otimizar essa consulta da seguinte maneira:
WITH QuantInfo AS ( SELECT o, qval FROM UNNEST(( SELECT APPROX_QUANTILES(sales, nbuckets) FROM `dataset.table` )) AS qval WITH offset o WHERE o > 0 ) SELECT individual_id, (SELECT (nbuckets + 1) - MIN(o) FROM QuantInfo WHERE sales <= QuantInfo.qval ) AS sales_third FROM `dataset.table`;
A versão otimizada oferece resultados semelhantes, mas não idênticos à consulta original, porque APPROX_QUANTILES
:
- Fornece uma agregação aproximada.
- Posiciona os valores restantes (o restante do número de linhas divididos por buckets) de maneira diferente.
Otimizar as UDFs
Prática recomendada: use UDFs de SQL para cálculos simples, porque o otimizador de consultas pode aplicar otimizações a definições de UDF em SQL. Use UDFs JavaScript para cálculos complexos que não são compatíveis com a UDF SQL.
Chamar uma UDF JavaScript requer a instanciação de um subprocesso. Acionar esse processo e executar a UDF afeta diretamente o desempenho da consulta. Se possível, use uma UDF nativa (SQL).
UDFs permanentes
É melhor criar funções SQL e JavaScript permanentes definidas pelo usuário em um conjunto de dados centralizado do BigQuery que pode ser invocado em consultas e visualizações lógicas, em vez de criar e chamar uma UDF no código sempre. Criar bibliotecas de toda a organização da lógica de negócios em conjuntos de dados compartilhados ajuda a otimizar o desempenho e usar menos recursos.
O exemplo a seguir mostra como uma UDF temporária é invocada em uma consulta:
CREATE TEMP FUNCTION addFourAndDivide(x INT64, y INT64) AS ((x + 4) / y); WITH numbers AS (SELECT 1 as val UNION ALL SELECT 3 as val UNION ALL SELECT 4 as val UNION ALL SELECT 5 as val) SELECT val, addFourAndDivide(val, 2) AS result FROM numbers;
É possível otimizar essa consulta substituindo a UDF temporária por uma permanente:
WITH numbers AS (SELECT 1 as val UNION ALL SELECT 3 as val UNION ALL SELECT 4 as val UNION ALL SELECT 5 as val) SELECT val, `your_project.your_dataset.addFourAndDivide`(val, 2) AS result FROM numbers;