Skip to content
cccskills
FreePublished on GitHub

trino-cost-optimization

Trino warehouse cost optimization — query scan cost analysis (system.runtime.queries/system.runtime.tasks), identifying expensive queries by CPU time and data scanned, scan reduction via partition pruning and file compaction, worker autoscaling patterns (scale-to-zero for batch), spot instance strategies for workers, S3 object storage cost (storage vs request costs), Iceberg compaction economics (fewer splits = fewer S3 GET requests), cost attribution by team/user, materialized view break-even analysis, result caching

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22 stars(GitHub 22 + cccskills 0)
Works withAWSKubernetes

Run score Not tested

See how to install

Files included (1)

  • SKILL.md11.3 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Trino Cost Optimization

When to Use

  • Cloud infrastructure bill is growing faster than data volume
  • Identifying which queries/teams are consuming the most resources
  • Reducing S3 GET request costs from excessive small-file scans
  • Rightsizing worker instance types for workload patterns
  • Implementing cost attribution for chargeback reporting

Query Cost Analysis

Identify Top Resource Consumers

-- Top 20 most expensive queries by CPU time (last 24h)
SELECT
    q.query_id,
    q.user,
    q.source,
    ROUND(q.total_cpu_time_secs / 3600.0, 2)   AS cpu_hours,
    ROUND(q.total_bytes_read / 1e9, 2)           AS gb_scanned,
    ROUND(q.wall_time_secs / 60.0, 1)            AS wall_min,
    q.state,
    SUBSTR(q.query, 1, 120)                      AS query_preview
FROM system.runtime.queries q
WHERE q.create_time >= NOW() - INTERVAL '24' HOUR
  AND q.state = 'FINISHED'
ORDER BY q.total_cpu_time_secs DESC
LIMIT 20;
-- Cost per team (proxy: CPU seconds as cost unit)
SELECT
    source,
    user,
    COUNT(*)                                          AS query_count,
    ROUND(SUM(total_cpu_time_secs) / 3600.0, 1)      AS total_cpu_hours,
    ROUND(SUM(total_bytes_read) / 1e12, 3)            AS total_tb_scanned,
    ROUND(AVG(wall_time_secs), 1)                     AS avg_wall_sec,
    COUNT(*) FILTER (WHERE state = 'FAILED')          AS failed_queries
FROM system.runtime.queries
WHERE create_time >= NOW() - INTERVAL '7' DAY
GROUP BY source, user
ORDER BY total_cpu_hours DESC
LIMIT 30;
-- Queries scanning more than 1TB (expensive full-table scans)
SELECT
    query_id,
    user,
    ROUND(total_bytes_read / 1e12, 2) AS tb_scanned,
    ROUND(total_cpu_time_secs / 3600.0, 2) AS cpu_hours,
    SUBSTR(query, 1, 200) AS query_preview
FROM system.runtime.queries
WHERE create_time >= NOW() - INTERVAL '7' DAY
  AND total_bytes_read > 1e12          -- > 1TB
  AND state = 'FINISHED'
ORDER BY total_bytes_read DESC
LIMIT 20;

Estimated Query Cost Model

# Simplified cost model for Trino on AWS
# Adjust coefficients for your cloud provider and instance pricing

def estimate_query_cost(
    cpu_time_sec: float,
    bytes_scanned: float,
    worker_hourly_rate_usd: float = 0.30,   # e.g. r5.2xlarge spot
    s3_get_cost_per_1k: float = 0.0004,      # S3 GET requests
    avg_rows_per_s3_get: int = 50000,         # rows per Parquet split
) -> dict:

    compute_cost = (cpu_time_sec / 3600) * worker_hourly_rate_usd
    s3_get_requests = bytes_scanned / (128 * 1024 * 1024)          # ~1 GET per 128MB split
    s3_cost = (s3_get_requests / 1000) * s3_get_cost_per_1k

    return {
        "compute_cost_usd": round(compute_cost, 4),
        "s3_get_cost_usd":  round(s3_cost, 6),
        "total_cost_usd":   round(compute_cost + s3_cost, 4),
    }

Scan Reduction Strategies

1. Enforce Partition Filters

Use query-partition-filter-required to force users to provide partition predicates on large tables:

# etc/catalog/iceberg.properties
iceberg.query-partition-filter-required=true   # fails queries without partition filter
iceberg.query-partition-filter-required-schemas=gold,silver

2. Limit Physical Data Scan per Query

// etc/rules.json — resource group with scan limit
{
  "tables": [
    {
      "group":   "analysts",
      "catalog": "iceberg",
      "schema":  "gold",
      "privileges": ["SELECT"],
      "hardPhysicalDataScanLimit": "500GB"   // reject queries scanning > 500GB
    }
  ]
}
# Per-query session limit
SET SESSION query_max_scan_physical_bytes = '200GB';

3. Compaction Reduces S3 Costs

More files = more S3 GET requests per query:

Before compaction: 10,000 × 10MB files → 10,000 S3 GETs per scan
After compaction:     200 × 500MB files →    200 S3 GETs per scan
Cost reduction: 98% fewer S3 GET requests
-- Run compaction to reduce file count and S3 requests
ALTER TABLE iceberg.silver.orders EXECUTE optimize(file_size_threshold => '256MB');

Worker Autoscaling

Kubernetes HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: trino-worker-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: trino-worker
  minReplicas: 2      # keep warm for interactive queries
  maxReplicas: 20
  metrics:
    - type: External
      external:
        metric:
          name: trino_queued_queries    # from Prometheus adapter
        target:
          type: AverageValue
          averageValue: "5"             # scale up when > 5 queries queued per worker
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type:          Pods
          value:         4
          periodSeconds: 60             # add up to 4 workers/min
    scaleDown:
      stabilizationWindowSeconds: 600   # 10-min cooldown before scale-down
      policies:
        - type:          Pods
          value:         2
          periodSeconds: 120

Scale-to-Zero for Batch Workloads

For batch jobs that run nightly, scale workers to 0 during idle hours:

# Airflow DAG: scale Trino workers before/after batch run
from airflow.providers.cncf.kubernetes.operators.kubernetes_pod import KubernetesPodOperator

scale_up = KubernetesPodOperator(
    task_id = 'scale_trino_workers_up',
    image   = 'bitnami/kubectl:latest',
    cmds    = ['kubectl', 'scale', 'deployment/trino-worker',
               '--replicas=10', '-n', 'trino'],
)

scale_down = KubernetesPodOperator(
    task_id = 'scale_trino_workers_down',
    image   = 'bitnami/kubectl:latest',
    cmds    = ['kubectl', 'scale', 'deployment/trino-worker',
               '--replicas=2', '-n', 'trino'],
)

scale_up >> run_batch_pipeline >> scale_down

Spot Instance Strategy

Use spot/preemptible instances for workers (not coordinator):

# Kubernetes node selector for spot workers
worker:
  nodeSelector:
    node.kubernetes.io/lifecycle: spot
  tolerations:
    - key:    "node.kubernetes.io/lifecycle"
      value:  "spot"
      effect: "NoSchedule"
# AWS Node Group with mixed instance types
ManagedNodeGroups:
  - name: trino-workers-spot
    instanceTypes: ["r5.4xlarge", "r5a.4xlarge", "r5d.4xlarge"]
    spot: true
    minSize: 2
    maxSize: 20

Enable fault-tolerant execution so spot interruptions don't fail queries:

# etc/config.properties
retry-policy=TASK
task-retry-attempts-per-task=4

Materialized View Break-Even

A materialized view is worth it when:

query_frequency × query_scan_cost > refresh_cost + storage_cost
-- Estimate MV break-even
WITH costs AS (
    SELECT
        -- How much the base query costs per run
        ROUND(total_bytes_read / 1e12, 3) AS base_tb_per_run,
        ROUND(total_cpu_time_secs / 3600.0, 2) AS base_cpu_hours
    FROM system.runtime.queries
    WHERE query LIKE '%FROM iceberg.silver.orders%GROUP BY%'
      AND create_time >= NOW() - INTERVAL '7' DAY
    ORDER BY create_time DESC
    LIMIT 10
)
SELECT
    AVG(base_tb_per_run)                    AS avg_tb_per_run,
    AVG(base_cpu_hours)                     AS avg_cpu_hours_per_run,
    COUNT(*) * 7.0 / 7                      AS runs_per_day,
    -- If MV refresh scans same data once/day:
    'Breakeven at ' || CAST(ROUND(1.0 / (COUNT(*) * 7.0 / 7), 1) AS VARCHAR) || ' runs/day' AS breakeven
FROM costs;

Cost Attribution Reporting

from airflow.providers.trino.hooks.trino import TrinoHook

def generate_weekly_cost_report() -> list[dict]:
    hook = TrinoHook(trino_conn_id='trino_default')

    rows = hook.get_records("""
        SELECT
            COALESCE(source, 'unknown')                               AS team,
            user,
            COUNT(*)                                                  AS queries,
            ROUND(SUM(total_cpu_time_secs) / 3600.0, 1)              AS cpu_hours,
            ROUND(SUM(total_bytes_read) / 1e12, 3)                    AS tb_scanned,
            -- Estimated cost: $0.30/cpu-hour + $0.0004/1000 S3 GETs
            ROUND(
                SUM(total_cpu_time_secs) / 3600.0 * 0.30 +
                SUM(total_bytes_read) / (128e6) / 1000 * 0.0004,
                2
            ) AS estimated_cost_usd
        FROM system.runtime.queries
        WHERE create_time >= NOW() - INTERVAL '7' DAY
          AND state = 'FINISHED'
        GROUP BY 1, 2
        ORDER BY estimated_cost_usd DESC
        LIMIT 50
    """)

    return [
        {'team': r[0], 'user': r[1], 'queries': r[2],
         'cpu_hours': r[3], 'tb_scanned': r[4], 'cost_usd': r[5]}
        for r in rows
    ]

Storage Cost Optimization

-- Find over-retained data (partitions older than policy)
SELECT
    partition,
    ROUND(total_size / 1e9, 1)      AS total_gb,
    record_count,
    file_count
FROM iceberg.bronze."orders_raw$partitions"
WHERE CAST(partition.ingested_date AS DATE) < CURRENT_DATE - INTERVAL '30' DAY
ORDER BY total_size DESC;

-- Drop old Bronze partitions (3× faster and cheaper than DELETE)
ALTER TABLE iceberg.bronze.orders_raw
DROP PARTITION WHERE ingested_date < DATE '2024-01-01';
-- Find tables without compression (uncompressed Parquet wastes storage)
SELECT table_name, table_schema,
       element_at(properties, 'compression_codec') AS codec
FROM iceberg.information_schema.tables
WHERE table_schema IN ('bronze', 'silver', 'gold')
  AND element_at(properties, 'compression_codec') IS DISTINCT FROM 'ZSTD';

Anti-Patterns

  1. No scan limit for analyst queries — an analyst accidentally running SELECT * FROM iceberg.silver.events (5TB) costs as much as running 50 normal queries; always set hardPhysicalDataScanLimit per group.
  2. Keeping Bronze data forever — raw ingest tables grow unbounded; define a retention policy (e.g., 30 days for Bronze, 1 year for Silver) and automate partition drops.
  3. Running large batch jobs during business hours — batch workloads compete with interactive analysts for the same workers; schedule heavy batches at night with dedicated resource groups.
  4. Spot workers without fault-tolerant execution — a spot interruption without FTE retries kills all in-flight queries; always pair spot workers with retry-policy=TASK.
  5. Not compacting Iceberg tables — 10,000 small files means 10,000 S3 GET requests per full-table scan; compacting to 200 files reduces S3 costs by ~98%.

References

  • Query system tables: trino.io/docs/current/connector/system.html
  • Resource group scan limits: trino.io/docs/current/admin/resource-groups.html
  • Fault-tolerant execution: trino.io/docs/current/admin/fault-tolerant-execution.html
  • Related skills: [[trino-admin-cluster-health]], [[trino-resource-group-governance]], [[trino-file-layout-optimization]], [[trino-iceberg-best-practices]]

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

AIOps autonomous incident response agent — LLM-driven diagnosis loop (Claude tool-use agent with kubectl/SQL/Prometheus tools), alert-to-action pipeline (PagerDuty webhook → agent trigger), automated RCA generation (failure taxonomy + log correlation), self-healing action executor with approval gate, incident severity classification, runbook automation (structured YAML runbooks executed by agent), escalation logic, incident timeline auto-generation, Slack integration for human-in-the-loop approvals

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

AIOps capacity planning agent — predictive resource forecasting (Prophet/linear regression on Prometheus metrics), Kubernetes HPA/VPA right-sizing recommendations, node capacity headroom calculator, Kafka partition and broker capacity model, Spark executor sizing from job history, data lake storage growth forecast (S3/GCS), cluster autoscaler simulation, automatic HPA threshold tuning, cost-per-job attribution, capacity planning report generator

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

AIOps infrastructure anomaly detection — statistical baseline (z-score/IQR/seasonal decomposition), Prometheus anomaly rules (predict_linear/stddev_over_time/MAD), ML-based detection (Isolation Forest/Prophet/LSTM autoencoder on metrics), metric correlation clustering, automated alert threshold tuning from historical data, Kubernetes resource anomaly detection, data pipeline anomaly signals (row count z-score/freshness drift/throughput drop), Python sklearn/Prophet integration, Grafana anomaly panel

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

AIOps observability copilot — natural language to PromQL/LogQL translation, alert explanation in plain English (what fired/why/impact), Grafana dashboard auto-generation from service topology, anomaly narrative generation from metric patterns, on-call context enrichment (related alerts/recent deploys/runbook links), log pattern clustering for noise reduction, SLO status explanation, automated weekly observability health digest

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

AIOps continuous platform optimization agent — autonomous optimization loop (observe→analyze→recommend→apply), Kubernetes resource rightsizing (VPA recommendation reader + apply), Kafka consumer lag auto-scale, Spark job configuration tuning from history, idle resource detection (unused deployments/PVCs/topics), compaction and VACUUM scheduling, auto-ANALYZE stale statistics, cost savings attribution, optimization audit trail, human approval gate for high-risk changes

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

AIOps autonomous query cost analyzer — Trino system.runtime.query_history cost SQL (CPU time/peak memory/bytes scanned), ClickHouse system.query_log top expensive queries, Spark UI cost attribution by user/job/DAG, BigQuery INFORMATION_SCHEMA.JOBS cost analysis, LLM-driven query rewrite recommendations (missing partition filters/broadcast hints/aggregation pushdown), cost anomaly detection (user over daily budget), automated query tagging, chargeback report by team/project

The English summary is being prepared. Showing the original description.

ivanshamaev/de-agent-skills22Updated May 20, 2026

See all skills by ivanshamaev

Report a problem with this skill