首頁 / Skills / 開發提效 / BigQuery 最佳化 BigQuery Optimization
開發提效

BigQuery 最佳化 BigQuery Optimization

GoogleApache-2.0Skill 語言: 英文
授權已核對不含腳本依賴外部服務需要金鑰
演示真實執行紀錄 · claude-sonnet-5-5 · 2026年10月
Optimize this BigQuery query (project shop-prod, I don't know the region): SELECT * FROM shop.orders WHERE EXTRACT(YEAR FROM order_ts) = 2025 AND customer_id NOT IN (SELECT customer_id FROM shop.blocked) ORDER BY order_ts
Skill: bigquery-optimization
Read: references/sql_optimization.md
Read: references/table_partitioning_clustering.md

Scope: project shop-prod, region us. You didn't give a region, so I assumed us. If shop lives elsewhere, use your region in any INFORMATION_SCHEMA queries (for example region-europe-west1). I haven't run anything against your project. This rewrite comes from the query text alone, and I'm assuming order_ts is a TIMESTAMP.

Optimized query

SELECT
  order_id,        -- replace with the columns you actually need
  customer_id,
  order_ts
FROM
  `shop-prod.shop.orders`
WHERE
  order_ts >= TIMESTAMP '2025-01-01 00:00:00'
  AND order_ts <  TIMESTAMP '2026-01-01 00:00:00'
  AND customer_id NOT IN (
    SELECT customer_id
    FROM `shop-prod.shop.blocked`
    WHERE customer_id IS NOT NULL
  )
ORDER BY
  order_ts
LIMIT 1000;  -- remove or adjust if you really need every row

Summary of optimizations

  1. Replaced EXTRACT(YEAR FROM order_ts) = 2025 with a range filter. A function on the column prevents partition pruning and block pruning. A plain range on order_ts lets BigQuery prune statically.
  2. Added WHERE customer_id IS NOT NULL to the NOT IN subquery. This lets BigQuery use an anti-hash join instead of the slower left outer hash join.
    • Behavior change: if shop.blocked contains a NULL customer_id, the original query returns zero rows, because NOT IN with a NULL evaluates to NULL. The rewrite returns the rows you almost certainly intended. If you somehow relied on the old behavior, tell me.
  3. Replaced SELECT * with an explicit column list. This reads less data. I don't know your schema, so fill in the columns you need.
  4. Added LIMIT to the ORDER BY. A full sort of a year of orders is expensive. If you need all rows, drop the LIMIT, or consider whether the sort is needed at all.

Table layout (biggest lever if the table is large)

The range filter only prunes partitions if shop.orders is partitioned on order_ts. To check, run:

bq show --format=prettyjson shop-prod:shop.orders

Look at timePartitioning, clustering and requirePartitionFilter in the output.

If the table is not partitioned, and each day holds roughly 10 GB or more (otherwise cluster only), you can create a partitioned copy:

CREATE TABLE `shop-prod.shop.orders_partitioned`
  PARTITION BY TIMESTAMP_TRUNC(order_ts, DAY)
  CLUSTER BY customer_id
  OPTIONS (require_partition_filter = TRUE)
AS
SELECT * FROM `shop-prod.shop.orders`;

You can't convert the existing table in place. Note that require_partition_filter = TRUE makes any query without an order_ts filter fail.

Validate before running

A dry run shows the bytes the query would process, and it costs nothing:

bq query --use_legacy_sql=false --dry_run "<the optimized query>"

Run it on the original query and on the rewrite, and compare totalBytesProcessed. The dry run won't show savings from clustering, since those happen at execution time.

These changes should improve cost-efficiency, but I can't promise a particular saving until you've compared the dry-run numbers.

Trial with only the Skill and Read tools: no Google Cloud access, no gcloud or bq. So only the SQL-rewrite path was exercised, from the query text alone; the model proposed the bq show and dry-run commands but did not run them. Capacity, billing and gcloud workflows were read but not tried.

它做什麼
把 Google 最佳化 BigQuery 的做法交給模型:改寫 SQL、提出資料表結構方案、說明計費選擇;涉及費用的變更則要求交給你自己執行,而不是由模型代跑。

運作方式

  1. SQL 最佳化:一份具體規則清單(以範圍條件取代 EXTRACT、對 NOT IN 子查詢排除空值、ORDER BY 搭配 LIMIT、避免最外層 SELECT *、先彙總再聯結等),最後列出改了什麼。
  2. 資料表設計:分區與叢集如何選擇、DDL 範本、把未分區的資料表遷移成分區資料表、require_partition_filter。
  3. 儲存與計費:邏輯儲存與實體儲存、時間旅行、分區到期,以及何時適合使用搜尋索引、具體化檢視表或 BI Engine。
  4. 容量:如何解讀 Slot Estimator 對隨需計費與 Editions 的建議。購買承諾、調整保留與變更計費模式一律交由你在 Cloud Console 操作。

適合
最佳化昂貴的查詢、設計或修正大型資料表、檢視 BigQuery 帳單。

限制
SQL 改寫只需查詢文字即可進行;分析類的部分需要 Google Cloud SDK 與你專案的存取權限,也無法取代你自己查看 dry run 的數字。

說明與風險

中風險:沒有腳本,但指令會讓代理對你的 Google Cloud 專案執行 `gcloud` 與 `bq`。這需要安裝 Google Cloud SDK、已登入的帳號(或服務帳戶金鑰檔)、帳單帳戶與 IAM 角色(文中提到 BigQuery 管理員、資料編輯者、工作使用者)。準備步驟包含 `gcloud config set project` 與 `gcloud services enable`,會變更專案設定,另有一條安裝配套 Skill 的指令(`npx skills add ...`)。Skill 也要求為它自己發出的 `gcloud` 呼叫加上用量歸因標記,並在傳給 Google 的 User-Agent 中加入 Skill 名稱與版本,你可以要求關閉。它明確要求代理不要自行購買承諾、變更計費模式或執行 DDL,而是提出方案由你執行。即便如此,每條指令請先看清楚再核准,先在非正式環境專案試用,並記得查詢與儲存變更都會產生費用。我們的試用只走了 SQL 改寫這條路徑,並未連線雲端。

SKILL.md 原文套件內共 11 個檔案