Práticas recomendadas para funções
Este documento descreve como otimizar consultas que usam funções SQL.
Otimize a comparação de strings
Prática recomendada: sempre que possível, use LIKE
em vez de REGEXP_CONTAINS
.
No BigQuery, pode usar a função
REGEXP_CONTAINS
ou o operador LIKE
para comparar strings. REGEXP_CONTAINS
oferece mais funcionalidades, mas também tem um tempo de execução mais lento. A utilização de LIKE
em vez de REGEXP_CONTAINS
é mais rápida, especialmente se não precisar de toda a capacidade das expressões regulares
que REGEXP_CONTAINS
oferece, por exemplo, a correspondência de carateres universais.
Considere a seguinte utilização da função REGEXP_CONTAINS
:
SELECT dim1 FROM `dataset.table1` WHERE REGEXP_CONTAINS(dim1, '.*test.*');
Pode otimizar esta consulta da seguinte forma:
SELECT dim1 FROM `dataset.table` WHERE dim1 LIKE '%test%';
Otimize as funções de agregação
Prática recomendada: se o seu exemplo de utilização o permitir, use uma função de agregação aproximada.
Se a função de agregação SQL que está a usar tiver uma função de aproximação equivalente, a função de aproximação produz um desempenho de consulta mais rápido. Por
exemplo, em vez de usar
COUNT(DISTINCT)
,
use
APPROX_COUNT_DISTINCT
.
Para mais informações, consulte as
funções de agregação aproximadas.
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 a seguinte utilização da função COUNT
:
SELECT dim1, COUNT(DISTINCT dim2) FROM `dataset.table` GROUP BY 1;
Pode otimizar esta consulta da seguinte forma:
SELECT dim1, APPROX_COUNT_DISTINCT(dim2) FROM `dataset.table` GROUP BY 1;
Otimize as funções de quantil
Prática recomendada: sempre que possível, use APPROX_QUANTILE
em vez de NTILE
.
A execução de uma consulta que contenha a função
NTILE
pode falhar com um erro
Resources exceeded
se existirem demasiados elementos a ORDER BY
numa única partição, o que faz com que o volume de dados aumente.
A janela analítica não está dividida, pelo que o cálculo NTILE
requer um ORDER BY
global para todas as linhas na tabela a serem processadas por um único trabalhador/ranhura.
Experimente usar
APPROX_QUANTILES
em alternativa. Esta função permite que a consulta seja executada de forma mais eficiente porque não requer um ORDER BY
global para todas as linhas na tabela.
Considere a seguinte utilização da função NTILE
:
SELECT individual_id, NTILE(nbuckets) OVER (ORDER BY sales desc) AS sales_third FROM `dataset.table`;
Pode otimizar esta consulta da seguinte forma:
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 dá resultados semelhantes, mas não idênticos, à consulta original, porque APPROX_QUANTILES
:
- Fornece uma agregação aproximada.
- Coloca os valores restantes (o resto do número de linhas dividido por grupos) de forma diferente.
Otimize as FDU
Prática recomendada: use FDUs SQL para cálculos simples, porque o otimizador de consultas pode aplicar otimizações a definições de FDUs SQL. Use UDFs de JavaScript para cálculos complexos que não são suportados pela UDF de SQL.
Chamar uma FDU JavaScript requer a instanciação de um subprocesso. A ativação deste processo e a execução da FDU afetam diretamente o desempenho das consultas. Se possível, use uma UDF nativa (SQL) em alternativa.
FDUs persistentes
É melhor criar funções SQL e JavaScript definidas pelo utilizador persistentes num conjunto de dados do BigQuery centralizado que pode ser invocado em consultas e em vistas lógicas, em vez de criar e chamar uma FDU no código sempre que necessário. A criação de bibliotecas de lógica empresarial ao nível da organização em conjuntos de dados partilhados ajuda a otimizar o desempenho e a usar menos recursos.
O exemplo seguinte mostra como uma FDU temporária é invocada numa 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;
Pode otimizar esta consulta substituindo a FDU temporária por uma FDU persistente:
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;