函式的最佳做法
本文件說明如何最佳化使用 SQL 函式的查詢。
最佳化字串比較
最佳做法:盡可能使用 LIKE
而非 REGEXP_CONTAINS
。
在 BigQuery 中,您可以使用 REGEXP_CONTAINS
函式或 LIKE
運算子來比較字串。REGEXP_CONTAINS
提供更多功能,但執行時間較慢。使用 LIKE
而非 REGEXP_CONTAINS
會更快速,特別是如果您不需要 REGEXP_CONTAINS
提供的規則運算式完整功能 (例如萬用字元比對),更是如此。
請參考下列 REGEXP_CONTAINS
函式的使用方式:
SELECT dim1 FROM `dataset.table1` WHERE REGEXP_CONTAINS(dim1, '.*test.*');
您可以按照下列方式最佳化這項查詢:
SELECT dim1 FROM `dataset.table` WHERE dim1 LIKE '%test%';
改善匯總函式
最佳做法:如果您的應用實例支援的話,請使用近似匯總函式。
如果您使用的 SQL 匯總函式有等同的近似函式,近似函式可提供更快的查詢效能。例如,請改用 APPROX_COUNT_DISTINCT
,而非 COUNT(DISTINCT)
。詳情請參閱近似匯總函式。
您也可以使用 HyperLogLog++
函式來計算近似值 (包括自訂近似匯總)。詳情請參閱 GoogleSQL 參考資料中的 HyperLogLog++ 函式。
請參考下列 COUNT
函式的使用方式:
SELECT dim1, COUNT(DISTINCT dim2) FROM `dataset.table` GROUP BY 1;
您可以按照下列方式最佳化這項查詢:
SELECT dim1, APPROX_COUNT_DISTINCT(dim2) FROM `dataset.table` GROUP BY 1;
最佳化分位數函式
最佳做法:盡可能使用 APPROX_QUANTILE
而非 NTILE
。
如果單一區隔中 ORDER BY
的元素過多,導致資料量增加,執行包含 NTILE
函式的查詢可能會失敗,並顯示 Resources exceeded
錯誤。分析時間區間並未分割,因此 NTILE
運算需要全域 ORDER BY
,才能由單一 worker/運算單元處理資料表中的所有資料列。
請改用 APPROX_QUANTILES
。這項函式不需要為資料表中的所有資料列建立全域 ORDER BY
,因此可讓查詢更有效率地執行。
請參考下列 NTILE
函式的使用方式:
SELECT individual_id, NTILE(nbuckets) OVER (ORDER BY sales desc) AS sales_third FROM `dataset.table`;
您可以按照下列方式最佳化這項查詢:
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`;
經過最佳化的版本會傳回與原始查詢相似但不完全相同的結果,因為 APPROX_QUANTILES
:
- 提供近似匯總。
- 以不同方式放置餘數值 (資料列數除以值區後的餘數)。
最佳化 UDF
最佳做法:請使用 SQL UDF 進行簡單計算,因為查詢最佳化工具可將最佳化套用至 SQL UDF 定義。使用 JavaScript UDF 執行 SQL UDF 不支援的複雜計算。
呼叫 JavaScript UDF 需要例項化子程序。直接啟動這項程序並執行 UDF 會影響查詢成效。如果可行,請改用原生 (SQL) UDF。
永久 UDF
建議您在集中式 BigQuery 資料集中建立持久的使用者定義 SQL 和 JavaScript 函式,以便在各項查詢和邏輯檢視中叫用,而非每次在程式碼中建立及叫用 UDF。在共用資料集內建立全組織的商業邏輯程式庫,有助於提升效能並減少資源用量。
以下範例說明如何在查詢中叫用臨時 UDF:
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;
您可以將暫時性 UDF 替換為永久性 UDF,藉此最佳化這項查詢:
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;