Bonnes pratiques pour les fonctions
Ce document explique comment optimiser les requêtes qui utilisent des fonctions SQL.
Optimiser la comparaison de chaînes
Bonne pratique : dans la mesure du possible, utilisez LIKE
au lieu de REGEXP_CONTAINS
.
Dans BigQuery, vous pouvez utiliser la fonction REGEXP_CONTAINS
ou l'opérateur LIKE
pour comparer les chaînes. REGEXP_CONTAINS
fournit plus de fonctionnalités, mais son temps d'exécution est plus lent. L'utilisation de LIKE
au lieu de REGEXP_CONTAINS
est plus rapide, en particulier si vous n'avez pas besoin de toute la puissance des expressions régulières fournies par REGEXP_CONTAINS
, par exemple pour la mise en correspondance d'un caractère générique.
Pensez à utiliser la fonction REGEXP_CONTAINS
suivante :
SELECT dim1 FROM `dataset.table1` WHERE REGEXP_CONTAINS(dim1, '.*test.*');
Vous pouvez optimiser cette requête comme suit :
SELECT dim1 FROM `dataset.table` WHERE dim1 LIKE '%test%';
Optimiser les fonctions d'agrégation
Bonne pratique : Si votre cas d'utilisation le permet, utilisez une fonction d'agrégation approximative.
Si la fonction d'agrégation SQL que vous utilisez est dotée d'une fonction d'approximation équivalente, celle-ci accélère les performances des requêtes. Par exemple, au lieu d'utiliser COUNT(DISTINCT)
, utilisez APPROX_COUNT_DISTINCT
.
Pour en savoir plus, consultez la section Fonctions d'agrégation approximative.
Vous pouvez également utiliser des fonctions HyperLogLog++
pour effectuer des approximations (y compris des agrégations approximatives personnalisées). Pour en savoir plus, consultez la page Fonctions HyperLogLog++ dans la documentation de référence sur GoogleSQL.
Envisagez d'utiliser la fonction COUNT
suivante :
SELECT dim1, COUNT(DISTINCT dim2) FROM `dataset.table` GROUP BY 1;
Vous pouvez optimiser cette requête comme suit :
SELECT dim1, APPROX_COUNT_DISTINCT(dim2) FROM `dataset.table` GROUP BY 1;
Optimiser les fonctions de quantile
Bonne pratique : dans la mesure du possible, utilisez APPROX_QUANTILE
au lieu de NTILE
.
L'exécution d'une requête contenant la fonction NTILE
peut échouer et générer une erreur Resources exceeded
s'il y a de trop nombreux éléments trier avec ORDER BY
dans une seule partition, ce qui entraîne une augmentation du volume de données.
La fenêtre analytique n'étant pas partitionnée, le calcul NTILE
nécessite une fonction globale ORDER BY
pour toutes les lignes de la table à traiter par un seul nœud de calcul/emplacement.
Utilisez plutôt APPROX_QUANTILES
. Cette fonction permet d'exécuter plus efficacement la requête, car elle ne nécessite pas de fonction globale ORDER BY
pour toutes les lignes de la table.
Envisagez d'utiliser la fonction NTILE
suivante :
SELECT individual_id, NTILE(nbuckets) OVER (ORDER BY sales desc) AS sales_third FROM `dataset.table`;
Vous pouvez optimiser cette requête comme suit :
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`;
La version optimisée fournit des résultats semblables à la requête d'origine, mais pas identiques, car APPROX_QUANTILES
:
- Fournit une agrégation approximative.
- Place les valeurs restantes (le nombre de lignes restantes divisées par les buckets) d'une manière différente.
Optimiser les fonctions définies par l'utilisateur
Bonne pratique : Utilisez des fonctions SQL définies par l'utilisateur pour effectuer des calculs simples, car l'optimiseur de requête peut appliquer des optimisations aux définitions de fonctions SQL définies par l'utilisateur. Utilisez des UDF JavaScript pour les calculs complexes qui ne sont pas compatibles avec les UDF SQL.
L'appel d'une fonction UDF JavaScript nécessite l'instanciation d'un sous-processus. L'activation de ce processus et l'exécution de la fonction UDF ont un impact direct sur les performances des requêtes. Si possible, utilisez plutôt un fichier UDF (SQL) natif.
Fonctions persistantes définies par l'utilisateur
Il est préférable de créer des fonctions SQL et JavaScript persistantes définies par l'utilisateur dans un ensemble de données BigQuery centralisé pouvant être appelées dans les requêtes et les vues logiques, plutôt que de créer et d'appeler à chaque fois une fonction définie par l'utilisateur dans le code. La création de bibliothèques de logique métier à l'échelle de l'organisation dans des ensembles de données partagés permet d'optimiser les performances et d'utiliser moins de ressources.
L'exemple suivant montre comment une fonction temporaire définie par l'utilisateur est appelée dans une requête :
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;
Vous pouvez optimiser cette requête en remplaçant la fonction temporaire définie par l'utilisateur par une fonction persistante :
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;