Generated banner for Bigquery Optimization
Generated logo for Bigquery Optimization

Bigquery Optimization

GoogleOfficialPublished by Google

  • Skill
  • Tool integration
  • Cloud and DevOps
  • Apache-2.0
  • No issues found

From the author

Provides workflows to optimize BigQuery environments (capacity planning, editions), storage assets (partitioning, clustering, storage lifecycles, billing models), and SQL queries. Use when optimizing cost, modeling Edition migrations, rightsizing reservations, evaluating logical vs. physical storage, designing table partitioning/clustering, generating table DDL, migrating unpartitioned tables, managing partition expiration, optimizing individual SQL queries, or evaluating acceleration structures (search indexes, materialized views, BI Engine). Do not use for raw usage reporting (use bigquery-observability), query execution plan analysis, error troubleshooting, or diagnosing why a specific job was slow (use bigquery-troubleshooting).
— the description by Google

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The bigquery-optimization skill provides a structured approach to improving the cost-efficiency and performance of Google BigQuery environments. It covers capacity planning for Editions, storage lifecycle and billing model management, table partitioning and clustering strategies, and SQL query refinement. The skill emphasizes manual configuration through the Cloud Console for financial changes while providing templates and guidance for technical optimizations like materialized views, search indexes, and BI Engine acceleration.

What it does

  • Models cost-efficiency for BigQuery Editions and reservation rightsizing.
  • Provides DDL templates for table partitioning, clustering, and storage lifecycle management.
  • Guides the evaluation of physical vs. logical storage billing models.
  • Offers strategies for implementing acceleration structures like materialized views and search indexes.
  • Provides workflows for optimizing individual SQL queries to reduce slot-time and data read.
  • Includes strict guardrails for regional scope and cost-framing terminology.

When to use it

  • When you need to optimize BigQuery storage costs or evaluate billing model changes.
  • When designing table schemas to improve query performance via partitioning and clustering.
  • When migrating workloads between On-Demand and Editions.
  • When troubleshooting high-cost queries or identifying opportunities for BI Engine acceleration.
  • When managing data retention through TTL and partition expiration policies.

Advantages

  • Standardizes optimization practices across capacity, storage, and query layers.
  • Reduces manual research by providing clear decision frameworks for acceleration tools.
  • Ensures safe operations by requiring manual execution for financial or resource-intensive changes.
  • Promotes consistent regional scoping and attribution for all operations.

Usage examples

“How can I optimize storage costs for my dataset in us-east1?”
The agent will guide you through evaluating your storage billing model (logical vs. physical), checking compression ratios, and implementing lifecycle policies to expire old partitions.
“My dashboard is slow; should I use BI Engine or a materialized view?”
The agent will analyze your use case to recommend BI Engine for in-memory acceleration, materialized views for pre-aggregated data, or a combination of both.
“Generate DDL to partition my large unpartitioned table by day.”
The agent will provide the necessary CREATE TABLE or CTAS statements to migrate your data to a partitioned structure while enforcing partition filters.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/google/bigquery-optimization/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip bigquery-optimization.zip -d .agents/skills

Documentation by Google

BigQuery Optimization Workflow

Attribution

MUST READ: Before executing any gcloud, REST API, or MCP command, you MUST read Usage Attribution. For commands executed directly in the terminal (never in generated scripts, Terraform, or user code), prefix gcloud with CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:bigquery-optimization)" and append agent-skills/1.0 (skill:bigquery-optimization) to User-Agent headers.

Prerequisites & Environment Setup

Before executing optimization analyses, evaluating editions, or applying DDL modifications:

  1. Google Cloud SDK: Ensure the Google Cloud SDK is installed and configured.

  2. Project Selection: Set the active Google Cloud project:

    gcloud config set project {project_id}
  3. API Enablement: Ensure BigQuery and BigQuery Reservation APIs are enabled:

    gcloud services enable \
        bigquery.googleapis.com bigqueryreservation.googleapis.com
  4. Authentication: Authenticate the environment:

    • CLI tools and bq commands: gcloud auth login

    • SDKs and automation: gcloud auth application-default login

    • Service accounts: Set GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"

  5. Billing & IAM Roles:

    • Verify an active Google Cloud Billing account is attached to {project_id}.

    • Ensure appropriate IAM roles:

      • roles/bigquery.admin or roles/bigquery.resourceAdmin: Reservation and capacity commitment management.

      • roles/bigquery.dataEditor or roles/bigquery.admin: Modifying table schemas, partitioning, clustering, and storage billing models.

      • roles/bigquery.jobUser: Running evaluation queries.

  6. Companion Skills Installation: This skill is part of a 3-pillar operations suite (bigquery-observability, bigquery-optimization, bigquery-troubleshooting). If any companion skill is not yet installed in your environment, install the full suite:

    npx skills add google/skills --skill bigquery-observability --skill bigquery-optimization --skill bigquery-troubleshooting

    (If bigquery-observability is not installed, use the self-contained baseline formulas and query templates provided directly in the reference sections below).

Workflows

Determine the optimization focus of the user's request and follow the relevant workflow:

  • Telemetry & Observability Baseline: For direct raw usage telemetry, INFORMATION_SCHEMA queries, and baseline metric calculations, consult bigquery-observability (bigquery_observability). If the bigquery-observability companion skill is not available in the active environment, all optimization guidelines, DDL templates, and decision models across this skill and its reference guides are fully self-contained.

  • Capacity & Editions Modeling: Evaluate the cost-efficiency of migrating workloads from On-Demand to Editions, as well as rightsizing active Edition reservations, baseline commitments, and autoscaling caps.

    • Instructions: Read references/capacity_planning_editions.md to provide deep links to BigQuery's built-in recommendation UIs (e.g., Slot Estimator) and guide the user through UI navigation: 1. navigate to the Slot Estimator tab, 2. select 'On-Demand' as the source to analyze historical query volume, and 3. review the Cost-Optimized Recommendations and Slot Usage Chart.

  • Table & Storage Optimization: Optimize storage costs from a billing model, physical layout, and lifecycle perspective.

    • Billing Architecture: Read references/storage_billing_models.md for guidance on evaluating aggregate compression ratios (e.g. >2:1 threshold in US) to recommend Physical vs. Logical billing, noting that the break-even ratio depends on specific regional rates and custom enterprise contracts. When providing TABLE_STORAGE queries, always scope with WHERE table_schema = '{dataset_id}', use the regional dataset view, and warn that 0 rows indicates a region mismatch or lack of native tables rather than zero billable usage.

    • Partitioning & Clustering Strategy: Read references/table_partitioning_clustering.md to generate production DDL templates (CREATE TABLE, CTAS migrations for unpartitioned tables, and modifying clustering specifications), enforce pruning with require_partition_filter = true, and manage partition limits (up to 10,000 partitions/table).

    • Lifecycle Management: Read references/storage_lifecycle_management.md to pinpoint inactive data and define precise Time-to-Live (TTL) partition expirations, dataset expirations, and Time Travel window reductions.

    • Acceleration Structures: Read references/search_indexes.md to decide when to propose a search index for selective lookups over STRING or JSON data, write the CREATE SEARCH INDEX DDL, and tell the user how to verify index coverage and usage. Read references/materialized_views.md to decide when to propose a materialized view for repeated aggregations or joins over large base tables, write the CREATE MATERIALIZED VIEW DDL, and tell the user how to verify that smart tuning uses it. Read references/bi_engine.md to decide when to propose BI Engine vs. Materialized Views for BI dashboard acceleration, diagnose PARTIAL or DISABLED BI Engine fallback reasons (bi_engine_statistics), and combine BI Engine with materialized views that pre-join or pre-aggregate the data.

  • SQL Optimization: Optimize individual SQL queries to reduce slot-time and the amount of data read.

    • Instructions: Follow the instructions in references/sql_optimization.md to provide recommendations to the user on how to rewrite their SQL query to reduce slot-time and the amount of data read.

Execution Guardrails

  • Terminology & Cost Framing: Never promise or guarantee "cost-reduction" or "reducing expenditure." Always frame recommendations using the terminology "optimizing your bill" or "improving cost-efficiency."

  • Explicit Scope Framing & Region Resolution: Always state the target project_id and region at the very top of your response so the user immediately knows the exact scope being evaluated. Follow this 3-tier resolution hierarchy:

    1. Explicit Region: Use the region specified in the user's prompt (e.g., europe-west1).

    2. Contextual Region: Resolve the region from the specific dataset or resource mentioned in the context.

    3. Unspecified Fallback: Default to us / region-us, explicitly state that us was assumed as the default, and instruct the user to substitute their region if their resources reside elsewhere. Region Formatting: In Cloud Console deep links, use the region identifier directly (e.g., region=us, region=europe-west1). In SQL queries against INFORMATION_SCHEMA, use the regional dataset qualifier (e.g., region-us, region-europe-west1).

  • Zero-Row Result Guard: If querying TABLE_STORAGE with WHERE table_schema = '{dataset_id}' returns 0 rows, do not proceed with an empty or zero-usage evaluation. Treat this as an indicator that the dataset may reside in a different region or have no native tables; stop and prompt the user to confirm the dataset's regional location.

  • Populate Concrete Parameters: When generating URLs and SQL queries, always substitute known project_id and region values directly into the code and links. Never leave literal {project_id} or {location} placeholders for the user to manually edit.

  • No Autonomous Purchasing or Financial Mutations: Never provide the user with executable scripts (e.g., gcloud or bq shell commands like bq update --storage_billing_model=...) designed to autonomously purchase annual commitments, alter edition tier bindings, or mutate storage billing models. Always guide the user to execute commitment purchases, reservation changes, and storage billing model updates manually via the Cloud Console UI.

Files

references/table_partitioning_clustering.md

Table Partitioning & Clustering Strategy

Architectural guidelines, decision matrices, and DDL patterns for table design, query pruning optimization, and storage efficiency.

Table of Contents

  • 1. Decision Matrix: Partitioning vs. Clustering vs. Hybrid (Lines 22-32)

  • 2. Partitioning Design Principles (Lines 34-66)

    • Partitioning Types by Column Type (Lines 36-46)

    • Core Partitioning Invariants & Rules (Lines 48-66)

  • 3. Clustering Design Principles (Lines 68-88)

    • Clustering Rules & Mechanics (Lines 70-88)

  • 4. Production DDL Templates (Lines 90-178)

    • Recommended Hybrid Pattern (Partition + Cluster) (Lines 92-112)

    • Migrating an Existing Unpartitioned Table to Partitioned (Lines 114-135)

    • Modifying the Clustering Specification (Lines 137-178)

  • 5. Table Design & Recommendation Workflow (Given a Table or Schema) (Lines 180-235)

  • 6. Table Design Anti-Patterns & Architecture Constraints (Lines 237-263)

  • 7. Telemetry & Data Retrieval Reference (Lines 265-287)

1. Decision Matrix: Partitioning vs. Clustering vs. Hybrid

<!-- mdformat off -->

DimensionPartitioning (PARTITION BY)Clustering (CLUSTER BY)Hybrid (PARTITION BY + CLUSTER BY)
Best ForLow-cardinality values, temporal/date boundaries, date-based TTL retention.High-cardinality values, multiple filter/group-by columns, frequent DML modifications.Large temporal tables with multi-dimensional filtering (e.g., date + tenant/status).
Pruning MechanismPartition Pruning: Whole partitions are eliminated from scanning before execution.Block Pruning: Capacitor data blocks within files are skipped dynamically during execution.Two-tier pruning: Partition pruning narrows the time window, then block pruning skips blocks within partitions.
Cost EstimationKnown deterministically before query execution via dry-run (totalBytesProcessed).Estimated dynamically during execution as blocks are evaluated.Upfront partition scan bounds with execution-time block savings.
Storage LifecycleUnlocks partition-level TTL and 90-day long-term 50% storage price discount.No partition-level expiration (data is co-located across storage blocks).Enables partition TTL retention while optimizing intra-partition query performance.
LimitsUp to 10,000 partitions per table.Up to 4 clustering columns per table.10,000 partition limit applies; clustering operates within each partition.

<!-- mdformat on -->

2. Partitioning Design Principles

Partitioning Types by Column Type
  • TIMESTAMP Column: PARTITION BY TIMESTAMP_TRUNC(column_name, DAY)

  • DATE Column: PARTITION BY date_column (or for monthly granularity: PARTITION BY DATE_TRUNC(date_column, MONTH))

  • DATETIME Column: PARTITION BY DATETIME_TRUNC(datetime_column, DAY)

  • Ingestion-Time Partitioning: BigQuery assigns rows to partitions based on the ingestion time using the pseudo-column _PARTITIONDATE / _PARTITIONTIME.

  • Integer-Range Partitioning: Partition by an INT64 column using RANGE_BUCKET(column, GENERATE_ARRAY(start, end, interval)).

Core Partitioning Invariants & Rules
  • 10,000 Partition Quota Limit: Each partitioned table can have up to 10,000 partitions. If a table reaches or approaches this limit:

    • Solution: Widen the partition time unit (e.g., switch from HOUR to DAY, or DAY to MONTH) and cluster on the granular time column (e.g. partition by month, cluster by timestamp). BigQuery automatically clusters data blocks within each partition.

  • Enforce Partition Pruning (require_partition_filter = true): For large tables, always set require_partition_filter = true to force queries to supply a partition predicate in the WHERE clause, preventing accidental multi-terabyte unpruned full-table scans.

  • Avoid Over-Partitioning: Do not create hourly partitions for low-volume tables. Partitioning that results in a small amount of data per partition (approximately less than 10 GB) increases the table's metadata, and can affect metadata access times when querying the table.

  • Long-Term Storage Discount: Partitions that are not modified for 90 consecutive days automatically qualify for 50% cheaper long-term storage pricing.

3. Clustering Design Principles

Clustering Rules & Mechanics
  • Up to 4 High-Cardinality Filtering & Grouping Columns: Specify up to 4 high-cardinality filtering and grouping columns (WHERE filters and GROUP BY keys) in the CLUSTER BY clause.

  • Column Ordering is Critical: BigQuery clusters data hierarchically based on the order of columns specified:

    • Place the most frequently filtered column or the column with equality filters first (col1).

    • Place secondary filter columns, range filter columns, or GROUP BY/JOIN keys next (col2, col3, col4).

    • Trap: Filtering on col2 without a predicate on col1 significantly diminishes block pruning effectiveness.

  • Supported Data Types: STRING (first 1,024 characters), INT64, NUMERIC, BIGNUMERIC, BOOL, TIMESTAMP, DATE, DATETIME, GEOGRAPHY, RANGE.

  • Automatic Re-Clustering: BigQuery performs continuous, fully-managed background reclustering to maintain block sortedness as new data is appended or modified, at zero slot cost.

4. Production DDL Templates

CREATE OR REPLACE TABLE `{project_id}.{dataset_id}.events`
(
  event_id STRING,
  customer_id STRING,
  event_type STRING,
  event_timestamp TIMESTAMP,
  payload JSON
)
-- Partition by DATE, TIMESTAMP, DATETIME, or INT64 range column:
PARTITION BY TIMESTAMP_TRUNC(event_timestamp, DAY)
-- Cluster on up to 4 high-cardinality filtering and grouping columns:
CLUSTER BY customer_id, event_type
OPTIONS (
  require_partition_filter = true,
  partition_expiration_days = 365,
  description = 'High-volume events partitioned by day and clustered by customer'
);
Migrating an Existing Unpartitioned Table to Partitioned

You cannot directly convert an existing non-partitioned table to a partitioned table via ALTER TABLE, and it is not possible to use the OR REPLACE modifier to replace a table with a different kind of partitioning. Instead, use a CREATE TABLE ... PARTITION BY ... CLUSTER BY ... AS SELECT * FROM ... (CTAS) statement to create a new partitioned table by querying the data in the existing table (or DROP the table first and then recreate it)—partitioning by a DATE, TIMESTAMP, DATETIME, or INT64 (RANGE_BUCKET) column, clustering on up to 4 high-cardinality filtering and grouping columns (WHERE and GROUP BY), and setting require_partition_filter = true:

CREATE TABLE `{project_id}.{dataset_id}.events_partitioned`
  -- Partition by DATE, TIMESTAMP, DATETIME, or INT64 range column:
  PARTITION BY TIMESTAMP_TRUNC(event_timestamp, DAY)
  -- Cluster on up to 4 high-cardinality filtering and grouping columns:
  CLUSTER BY customer_id, event_type
  OPTIONS (require_partition_filter = TRUE)
AS
SELECT * FROM `{project_id}.{dataset_id}.events_unpartitioned`;
Modifying the Clustering Specification

Apply a new clustering specification to unpartitioned or partitioned tables in two steps. First, update the clustering specification of the table to match the new clustering:

bq update --clustering_fields=customer_id,status \
  {project_id}:{dataset_id}.{table_id}

The --clustering_fields value is a comma-separated list of column names to use for clustering.

Then, to cluster all rows according to the new clustering specification, run the following UPDATE statement. Propose this statement to the user rather than running it directly:

UPDATE `{project_id}.{dataset_id}.{table_id}`
SET customer_id = customer_id
WHERE true;

The UPDATE must supply a partition filter if the table has require_partition_filter = true, and a single job cannot modify more than 4,000 partitions (the per-job modification limit). For partitioned tables, re-cluster in bounded batches:

UPDATE `{project_id}.{dataset_id}.{table_id}`
SET customer_id = customer_id
WHERE {partition_column} >= '{range_start}'
  AND {partition_column} < '{range_end}';

Repeat over consecutive ranges of fewer than 4,000 partitions until the whole table is covered.

Tell the user that applying a new clustering specification to a table in long-term storage reverts that table to active storage pricing.

5. Table Design & Recommendation Workflow (Given a Table or Schema)

When asked to recommend a partitioning and clustering strategy for a specific table or schema:

  1. Step 1: Identify Partitioning Key & Time Granularity

    • Audit Existing Table Configuration: Before proposing changes, check INFORMATION_SCHEMA.COLUMNS (is_partitioning_column = 'YES', data_type, clustering_ordinal_position) and INFORMATION_SCHEMA.TABLE_OPTIONS (option_name = 'require_partition_filter') for the target dataset, or run bq show --format=prettyjson {project_id}:{dataset_id}.{table_id} (timePartitioning, rangePartitioning, clustering, requirePartitionFilter) to confirm whether the table already has DATE, TIMESTAMP, DATETIME, or INT64 integer-range partitioning, clustering columns, and partition filter enforcement.

    • Scan Column Types: Look for TIMESTAMP, DATE, or DATETIME columns representing primary event generation time.

    • Check the 10,000 Partition Quota Limit:

      • DAY Partitioning (Default): Optimal for 1–7 year lifespans (~365 to ~2,555 partitions).

      • HOUR Partitioning: Choose it only for tables with a high volume of data spanning a short date range — typically less than six months of timestamp values. Make sure the resulting partition count stays within the 10,000 partition limit.

      • MONTH or YEAR Partitioning: For historical archives (>10 years), partition by MONTH and cluster by the timestamp.

    • No Temporal Column: Evaluate integer range partitioning (RANGE_BUCKET) for incremental IDs, or ingestion-time partitioning (_PARTITIONTIME) for append-only log streams.

  2. Step 2: Select & Order Clustering Columns (Up to 4 Columns)

    • Candidate Columns: High-cardinality dimension columns frequently present in WHERE equality filters, JOIN ON clauses, or GROUP BY aggregations (e.g., customer_id, organization_id, status).

    • Column Ordering Rules:

      • col1: The most frequently filtered column or equality/tenant identifier (customer_id).

      • col2, col3: Secondary dimensions or range filter attributes (event_type, created_at).

      • Order Trap: Queries filtering on col2 without a predicate on col1 cannot perform efficient block pruning.

  3. Step 3: Output Production DDL & Guardrails

    • Generate complete CREATE TABLE DDL, including CTAS migrations. To modify a table's clustering specification, use the two-step sequence in Section 4.

    • Add require_partition_filter = true (ALTER TABLE {dataset_id}.{table_id} SET OPTIONS (require_partition_filter = true)) for high-volume production tables to prevent accidental unpruned full-table scans.

    • Add partition_expiration_days = N for staging, ETL, or rolling log tables to automate data cleanup.

6. Table Design Anti-Patterns & Architecture Constraints

  • ALTER TABLE Partitioning Invariant: BigQuery does not support altering an existing unpartitioned table to become partitioned. You must create a new partitioned table using CTAS or a load job. ALTER TABLE does not support setting or changing a table's clustering; use bq update --clustering_fields (Section 4).

  • Small-Partition Anti-Pattern (<10 GB per Partition): Prefer clustering over partitioning when partitioning would yield less than ~10 GB per partition. Creating many small partitions inflates table metadata and slows metadata access at query time without yielding scan savings. (Separately, on-demand query compute charges enforce a 10 MiB data processed minimum per referenced table and per query, regardless of table or partition size).

  • 1,024-Character String Limit: For STRING clustering columns, BigQuery evaluates only the first 1,024 characters for block pruning. Do not cluster on long free-text descriptions or raw JSON payloads; extract concise identifiers.

  • Streaming Buffer Compaction (__UNPARTITIONED__): Rows recently streamed via the BigQuery Storage Write API initially reside in the __UNPARTITIONED__ partition with a NULL _PARTITIONTIME. These rows cannot be pruned by partition filters until extracted into permanent partitions by BigQuery's background compaction.

  • Query Filter Optimization: To leverage partition and clustering pruning effectively in query execution, predicates must use compile-time constants. For query-level WHERE-clause rewrites and function anti-patterns, refer to the bigquery-optimization skill.

7. Telemetry & Data Retrieval Reference

If the bigquery-observability skill is available in your workspace, refer to its shared telemetry references for canonical query templates and schema dictionaries. All essential table design workflows, DDL templates, and remediation levers are self-contained within this guide.

  • Table Partitioning, Clustering & Filter Enforcement Audit: See the bigquery-observability skill (references/storage_footprints.md, section "Table Partitioning, Clustering & Filter Enforcement Audit") to query INFORMATION_SCHEMA.COLUMNS and INFORMATION_SCHEMA.TABLE_OPTIONS for unpartitioned tables, partitioning column types, clustering columns, and require_partition_filter.

  • High-Scan Referenced Tables Discovery: See the bigquery-observability skill (references/compute_ondemand_billable.md, section "CORE RULE: The Golden Base CTE (bytes_billed_cte)") to group INFORMATION_SCHEMA.JOBS_BY_PROJECT by query_info.query_hashes.normalized_literals for exact job-level total_bytes_billed and total_bytes_processed attribution, and unnest referenced_tables to discover candidate tables (do not sum job-level bytes across multi-table joins; cross-check candidate table size via total_logical_bytes in INFORMATION_SCHEMA.TABLE_STORAGE before recommending partitioning).

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs a command-line tool, Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Google
Publisher
Google (Official)
Source
google/skills · skills/cloud/bigquery-optimization · commit 2194d3b
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Google.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download bigquery-optimization.zip