Best Practices für Funktionen
In diesem Dokument wird beschrieben, wie Abfragen mithilfe von SQL-Funktionen optimiert werden.
Stringvergleich optimieren
Best Practice: Verwenden Sie nach Möglichkeit LIKE
anstelle von REGEXP_CONTAINS
.
In BigQuery können Sie die REGEXP_CONTAINS
-Funktion oder den LIKE
-Operator verwenden, um Strings zu vergleichen. REGEXP_CONTAINS
bietet mehr Funktionen, ist aber in der Ausführung langsamer. Die Verwendung von LIKE
anstelle von REGEXP_CONTAINS
bietet Tempovorteile. Dies gilt besonders, wenn Sie nicht die volle Leistung regulärer Ausdrücke benötigen, die REGEXP_CONTAINS
bietet, z. B. Platzhalterabgleich.
Betrachten Sie folgende Verwendung der REGEXP_CONTAINS
-Funktion:
SELECT dim1 FROM `dataset.table1` WHERE REGEXP_CONTAINS(dim1, '.*test.*');
Sie können diese Abfrage so optimieren:
SELECT dim1 FROM `dataset.table` WHERE dim1 LIKE '%test%';
Aggregationsfunktionen optimieren
Best Practice: Nutzen Sie eine ungefähre Aggregatfunktion, wenn Ihr Anwendungsfall dies unterstützt.
Wenn es zu der von Ihnen verwendeten SQL-Aggregatfunktion eine entsprechende Näherungsfunktion gibt, erhöhen Sie damit die Abfrageleistung. Nutzen Sie beispielsweise statt
COUNT(DISTINCT)
APPROX_COUNT_DISTINCT
.
Weitere Informationen finden Sie unter ungefähre Aggregatfunktionen.
Sie können auch HyperLogLog++
-Funktionen verwenden, um Näherungen (einschließlich benutzerdefinierter ungefährer Aggregationen) durchzuführen. Weitere Informationen finden Sie unter HyperLogLog++-Funktionen in der GoogleSQL-Referenz.
Betrachten Sie folgende Verwendung der COUNT
-Funktion:
SELECT dim1, COUNT(DISTINCT dim2) FROM `dataset.table` GROUP BY 1;
Sie können diese Abfrage so optimieren:
SELECT dim1, APPROX_COUNT_DISTINCT(dim2) FROM `dataset.table` GROUP BY 1;
Quantilfunktionen optimieren
Best Practice: Verwenden Sie nach Möglichkeit APPROX_QUANTILE
anstelle von NTILE
.
Das Ausführen einer Abfrage, die die NTILE
-Funktion enthält, kann mit dem Resources exceeded
-Fehler fehlschlagen, wenn es zu viele Elemente in einer einzelnen Partition ORDER BY
werden müssen, wodurch das Datenvolumen wächst.
Das Analysefenster ist nicht partitioniert. Deshalb benötigt die NTILE
-Berechnung einen globalen ORDER BY
, um alle Zeilen in der Tabelle von einem einzelnen Worker/Slot zu verarbeiten.
Verwenden Sie stattdessen APPROX_QUANTILES
. Mit dieser Funktion kann die Abfrage effizienter ausgeführt werden, da nicht für alle Zeilen in der Tabelle ein globales ORDER BY
erforderlich ist.
Betrachten Sie folgende Verwendung der NTILE
-Funktion:
SELECT individual_id, NTILE(nbuckets) OVER (ORDER BY sales desc) AS sales_third FROM `dataset.table`;
Sie können diese Abfrage so optimieren:
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`;
Die optimierte Version liefert ähnliche, aber nicht identische Ergebnisse wie die ursprüngliche Abfrage, weil APPROX_QUANTILES
:
- - eine ungefähre Zusammenfassung bereitstellt.
- - die Restwerte (die verbleibenden Zeilen, geteilt durch Buckets) auf andere Weise platziert.
UDFs optimieren
Best Practice: Verwenden Sie SQL-UDFs für einfache Berechnungen, da das Abfrageoptimierungstool Optimierungen auf SQL-UDF-Definitionen anwenden kann. Verwenden Sie JavaScript-UDFs für komplexe Berechnungen, die von SQL-UDF nicht unterstützt werden.
Für den Aufruf einer benutzerdefinierten JavaScript-Funktion ist die Instanziierung eines Java-Unterprozesses erforderlich. Das Starten dieses Vorgangs und das Ausführen der benutzerdefinierten Funktion wirken sich auf die Abfrageleistung aus. Verwenden Sie daher, falls möglich, stattdessen eine native (SQL) UDF.
Nichtflüchtige UDFs
Es ist besser, nichtflüchtige benutzerdefinierte SQL- und JavaScript-Funktionen in einem zentralisierten BigQuery-Dataset zu erstellen, das über Abfragen und logische Ansichten hinweg aufgerufen werden kann, statt jedes Mal eine UDF im Code zu erstellen und aufzurufen. Durch das Erstellen organisationsweiter Geschäftslogik-Bibliotheken in freigegebenen Datasets können Sie die Leistung optimieren und weniger Ressourcen verbrauchen.
Das folgende Beispiel zeigt, wie eine temporäre UDF in einer Abfrage aufgerufen wird:
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;
Um diese Abfrage zu optimieren ersetzen Sie die temporäre UDF durch eine 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;