GEMINI LABJP
NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Articles/Dev Tools
Dev Tools/2026-03-26Intermediate

Gemini API × BigQuery: AI-Powered Data Analysis — From Natural Language Queries to Actionable Insights

Learn how to combine Gemini API with BigQuery for natural language data analysis. Covers SQL auto-generation, result summarization, and production-ready patterns with practical Python code examples.

gemini-api277bigquerydata-analysis5python104sql2google-cloud6

You've got terabytes of data sitting in BigQuery, but not everyone on your team can write SQL to extract the insights they need. What if anyone could simply ask a question in plain English and get an analyzed result back?

By combining Gemini API with Google BigQuery, you can build a natural language data analysis pipeline that generates SQL from questions, executes queries, and summarizes results — all automatically. The walkthrough below is a complete Python implementation—real code you can point at your own datasets.

What you'll learn:

  • How to architect a Gemini × BigQuery integration
  • Auto-generating SQL from natural language using schema-aware prompts
  • Summarizing query results into business-friendly insights
  • Production considerations for security and cost management

Who this is for: Developers and data analysts familiar with BigQuery basics who want to enhance their analysis workflow with Gemini AI.

Prerequisites and Setup

What you'll need

  1. Google Cloud project — with BigQuery API and Vertex AI API (or a Google AI Studio API key) enabled
  2. Python 3.10+ — using the google-cloud-bigquery and google-genai packages
  3. A BigQuery dataset — we'll use the public bigquery-public-data.google_analytics_sample dataset as our example

Install the packages

pip install google-cloud-bigquery google-genai db-dtypes pandas

Configure your API key

import os
 
# Using Google AI Studio API key
os.environ["GOOGLE_API_KEY"] = "your-api-key-here"
 
# For Vertex AI, use service account authentication instead
# gcloud auth application-default login

Architecture Overview

The Gemini × BigQuery data analysis pipeline follows this flow:

User question (natural language)
    ↓
[Gemini API] Generate SQL using table schema context
    ↓
[BigQuery] Execute SQL and retrieve results
    ↓
[Gemini API] Summarize results and surface insights
    ↓
Output to report or dashboard

The key ingredient is passing table schema information to Gemini. With schema awareness, the model generates significantly more accurate SQL — correct column names, proper types, and valid joins.

Step 1: Extract BigQuery Schema Information

First, fetch the schema from your target tables and format it as context for Gemini.

from google.cloud import bigquery
 
client = bigquery.Client()
 
def get_table_schema(dataset_id: str, table_id: str) -> str:
    """Return table schema in a human-readable format."""
    table_ref = f"{client.project}.{dataset_id}.{table_id}"
    table = client.get_table(table_ref)
 
    schema_lines = [f"Table: {table_ref}"]
    schema_lines.append(f"Row count: ~{table.num_rows:,}")
    schema_lines.append(f"Columns:")
 
    for field in table.schema:
        nullable = "NULLABLE" if field.mode == "NULLABLE" else "REQUIRED"
        schema_lines.append(
            f"  - {field.name} ({field.field_type}, {nullable}): {field.description or 'No description'}"
        )
 
    return "\n".join(schema_lines)
 
# Example usage
schema_info = get_table_schema(
    "google_analytics_sample",
    "ga_sessions_20170801"
)
print(schema_info)

Sample output:

Table: your-project.google_analytics_sample.ga_sessions_20170801
Row count: ~170,366
Columns:
  - visitorId (INTEGER, NULLABLE): No description
  - visitNumber (INTEGER, NULLABLE): No description
  - visitId (INTEGER, NULLABLE): No description
  - visitStartTime (INTEGER, NULLABLE): No description
  ...

Step 2: Generate SQL from Natural Language with Gemini

Embed the schema into a system prompt and convert user questions into SQL queries.

from google import genai
 
# Initialize the Gemini client
genai_client = genai.Client()
 
def generate_sql(question: str, schema: str) -> str:
    """Generate a BigQuery SQL query from a natural language question."""
 
    system_prompt = f"""You are a BigQuery SQL expert.
Generate a SQL query that answers the user's question based on the following table schema.
 
{schema}
 
Rules:
- Output valid BigQuery Standard SQL only
- Return only the SQL query, no explanations
- Include appropriate LIMIT clauses to avoid returning excessive data
- Include the full project name in table references
- Do not include comments
"""
 
    response = genai_client.models.generate_content(
        model="gemini-2.5-flash",
        contents=question,
        config=genai.types.GenerateContentConfig(
            system_instruction=system_prompt,
            temperature=0.1,  # Low temperature for accurate SQL generation
        ),
    )
 
    # Strip markdown code block markers
    sql = response.text.strip()
    sql = sql.replace("```sql", "").replace("```", "").strip()
 
    return sql
 
# Example usage
question = "What are the top 10 traffic channels by session count?"
sql = generate_sql(question, schema_info)
print(sql)

Generated SQL example:

SELECT
  channelGrouping,
  COUNT(*) AS session_count
FROM
  `bigquery-public-data.google_analytics_sample.ga_sessions_20170801`
GROUP BY
  channelGrouping
ORDER BY
  session_count DESC
LIMIT 10

Validate SQL Before Execution

Never execute AI-generated SQL without validation. Use BigQuery's dry run feature to check syntax and estimate costs.

from google.cloud.bigquery import QueryJobConfig
 
def validate_sql(sql: str) -> dict:
    """Validate SQL with a dry run and return estimated bytes processed."""
    job_config = QueryJobConfig(dry_run=True, use_query_cache=False)
 
    try:
        query_job = client.query(sql, job_config=job_config)
        bytes_processed = query_job.total_bytes_processed
        return {
            "valid": True,
            "estimated_bytes": bytes_processed,
            "estimated_gb": round(bytes_processed / (1024**3), 4),
        }
    except Exception as e:
        return {"valid": False, "error": str(e)}
 
# Run validation
result = validate_sql(sql)
print(result)
# Output: {'valid': True, 'estimated_bytes': 148567232, 'estimated_gb': 0.1384}

Step 3: Execute Queries and Summarize Results with Gemini

Once validation passes, run the query and feed the results back to Gemini for analysis.

import pandas as pd
 
def execute_and_summarize(sql: str, question: str) -> str:
    """Execute SQL and summarize the results using Gemini."""
 
    # Execute the query
    df = client.query(sql).to_dataframe()
 
    # Convert the dataframe to a text representation
    result_text = df.to_string(index=False, max_rows=50)
 
    # Generate a summary with Gemini
    summary_prompt = f"""Summarize the following data analysis results in a way that a business stakeholder can understand.
 
## Original Question
{question}
 
## SQL Executed
{sql}
 
## Result Data
{result_text}
 
Please provide:
1. Key findings (the most important data points)
2. Notable trends or patterns
3. Recommended next actions
"""
 
    response = genai_client.models.generate_content(
        model="gemini-2.5-flash",
        contents=summary_prompt,
    )
 
    return response.text
 
# Example
summary = execute_and_summarize(sql, question)
print(summary)

Sample output:

## Analysis Summary

### Key Findings
- Organic Search dominates with approximately 43% of all sessions
- Social (22%) and Direct (18%) round out the top three channels

### Notable Patterns
- Paid Search accounts for less than 5% of sessions, highlighting the
  strength of organic acquisition strategies
- Referral traffic at ~10% suggests established external linking

### Recommended Actions
- Investigate Paid Search ROI to determine if increased spend is justified
- Break down Social traffic by platform for targeted optimization

Step 4: Build a Conversational Data Analysis Agent

Now let's combine all the pieces into an interactive analysis agent.

class GeminiBigQueryAgent:
    """A conversational agent for natural language BigQuery analysis."""
 
    def __init__(self, dataset_id: str, table_ids: list[str]):
        self.bq_client = bigquery.Client()
        self.genai_client = genai.Client()
        self.schemas = self._load_schemas(dataset_id, table_ids)
        self.history = []
 
    def _load_schemas(self, dataset_id, table_ids) -> str:
        """Load schemas for multiple tables."""
        all_schemas = []
        for tid in table_ids:
            schema = get_table_schema(dataset_id, tid)
            all_schemas.append(schema)
        return "\n\n".join(all_schemas)
 
    def ask(self, question: str) -> dict:
        """Process a question and return analysis results."""
        # 1. Generate SQL
        sql = generate_sql(question, self.schemas)
 
        # 2. Validate
        validation = validate_sql(sql)
        if not validation["valid"]:
            return {
                "error": f"SQL validation failed: {validation['error']}",
                "sql": sql,
            }
 
        # 3. Cost guard (require confirmation for queries over 1GB)
        if validation["estimated_gb"] > 1.0:
            return {
                "warning": f"Estimated scan: {validation['estimated_gb']}GB. Proceed?",
                "sql": sql,
            }
 
        # 4. Execute and summarize
        summary = execute_and_summarize(sql, question)
 
        # 5. Add to history
        self.history.append({
            "question": question,
            "sql": sql,
            "bytes": validation["estimated_bytes"],
        })
 
        return {
            "question": question,
            "sql": sql,
            "summary": summary,
            "estimated_cost_gb": validation["estimated_gb"],
        }
 
# Usage
agent = GeminiBigQueryAgent(
    dataset_id="google_analytics_sample",
    table_ids=["ga_sessions_20170801"]
)
 
result = agent.ask("What's the conversion rate by device category?")
print(result["summary"])

Production Security and Cost Management

SQL Injection Protection

Since AI-generated SQL is executed directly, implement guardrails to ensure only read operations are permitted.

import re
 
FORBIDDEN_PATTERNS = [
    r"\bDROP\b",
    r"\bDELETE\b",
    r"\bUPDATE\b",
    r"\bINSERT\b",
    r"\bCREATE\b",
    r"\bALTER\b",
    r"\bTRUNCATE\b",
]
 
def is_safe_sql(sql: str) -> bool:
    """Allow only read-only SQL statements."""
    upper_sql = sql.upper()
    for pattern in FORBIDDEN_PATTERNS:
        if re.search(pattern, upper_sql):
            return False
    return upper_sql.strip().startswith("SELECT") or upper_sql.strip().startswith("WITH")

Cost Management Best Practices

BigQuery charges based on the volume of data scanned, so cost control is essential.

  • Always dry run first: Use validate_sql to check estimated costs before execution
  • Set byte limits: Use QueryJobConfig(maximum_bytes_billed=1_000_000_000) for a 1GB cap
  • Leverage partitioning: Date-partitioned tables dramatically reduce scan volume
  • Use caching: Identical queries are served from BigQuery's automatic cache at no charge
# Execute with a cost cap
job_config = QueryJobConfig(
    maximum_bytes_billed=1_000_000_000  # 1GB limit
)
df = client.query(sql, job_config=job_config).to_dataframe()

Summary

Combining Gemini API with BigQuery opens the door to natural language data analysis that anyone on your team can use — no SQL expertise required. The architecture we've covered — schema-aware SQL generation, dry-run validation, and AI-powered summarization — provides a solid foundation for building internal analytics tools, Slack bots, or custom dashboards.

Start by experimenting with public datasets to get comfortable with the workflow, then gradually introduce your own data. The patterns we've covered here scale well from prototype to production.

If you're interested in building more sophisticated data analysis agents, check out [Build an AI Data Analysis Agent with Gemini API]((/articles/gemini-api/gemini-api-ai-data-analysis-agent) for in-depth agent design patterns. For improving SQL generation accuracy, [Getting Started with Natural Language SQL Conversion in Gemini]((/articles/gemini-api/gemini-text-to-sql-guide) is another great resource.

To dive deeper into the topics covered in this article,

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-04-17
Google Cloud Workflows × Gemini API Production Orchestration Guide: Timeouts, Retries, and Cost Control
A complete guide to orchestrating Gemini API calls in production using Google Cloud Workflows. Covers YAML step definitions, automatic retries, timeout configuration, and cost budget alerts with working code examples.
Dev Tools2026-04-08
Terraform × Gemini API: Complete Production Infrastructure Automation Guide — IaC Design Patterns for AI Applications on Google Cloud
Automate your entire Gemini API production infrastructure with Terraform. Covers IAM, Cloud Run, Vertex AI, Secret Manager, and CI/CD in one comprehensive IaC design guide.
Dev Tools2026-04-08
Automating Accessibility Audits with the Gemini API — A Design That Survives False Positives
Build a WCAG 2.2 audit pipeline with the Gemini API. Separate what can be measured from what needs judgment, then use structured output, baseline diffing, and tiered CI gates to keep false positives from killing the practice.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →