Start by clarifying scope (which query, timeframe, and affected user/queue). Then run a targeted diagnostic loop: identify the query, inspect plan-level IO/CPU, find hot tables/columns, and check disk/ table stats.1) Find the query and summary metrics- Query STL_QUERY for runtime, start/end, userid, and aborted flag.- Use SVL_QUERY_REPORT to get per-step CPU/ms and rowcounts.Example:sql
-- find recent long-running queries
select userid, query, starttime, endtime, elapsed/1000000.0 as seconds
from STL_QUERY
where endtime >= sysdate - 1
and elapsed > 600000000 -- >10 minutes
order by elapsed desc limit 10;
2) Inspect per-step CPU/IO and bottleneck steps- From SVL_QUERY_REPORT check steps with high "cpu_time" and "disk" columns, and "rows" vs "rows_out".- Look for steps with high "peak_memory_mb" or repeated spills to disk.3) Identify scanned blocks and table hotspots- STL_SCAN shows tbl, per-segment blocks scanned and rows read. High blocks_read relative to table size indicates full scans.sql
select s.tbl, t."table", sum(s.blocks) as blocks_scanned, max(s.rows) rows_read
from stl_scan s
join svv_table_info t on s.tbl = t.table_id
where s.query = 12345
group by s.tbl,t."table"
order by blocks_scanned desc;
4) Check table statistics and disk usage- SVV_TABLE_INFO shows size, unsorted and stats_off (% stale stats).- SVV_DISKUSAGE shows skew across slices and nodes (hot nodes).sql
select * from svv_table_info where table = 'schema.table';
select * from svv_diskusage where userid = <user> order by pct_capacity_used desc limit 20;
Key metrics to evaluate- elapsed time, cpu_time, read_io (disk bytes), blocks_scanned, rows_in/rows_out, peak_memory_mb, stats_off, skew (pct_used per slice), unsorted ratio, table size, data distribution key cardinality.Common root causes and fixes- Full table scans on large tables: add selective predicates, push filters early, create ZORDER/COMPOUND sort keys or interleave sort keys, and add appropriate distribution key to avoid reshuffle. Consider materialized views or pre-aggregations.- Stale or missing statistics: RUN ANALYZE on affected tables to refresh planner stats.- Skewed data/distribution: If one slice reads far more blocks, change distkey or use even distribution (diststyle key vs all vs even) or redistribute data; consider AUTO distribution for appropriate workloads.- Disk spills / insufficient memory: increase WLM query slot memory, move to a higher WLM queue with more memory, or rewrite query to reduce memory (break into temp tables, use CTAS, or sort/aggregate smaller partitions).- Large intermediate shuffles / network IO: Reorder joins to drive from smallest table, use distribution keys to collocate joins, use broadcast (DISTSTYLE ALL) for small dimension tables.- Wide or unsorted tables causing many blocks scanned: VACUUM to resort and reclaim deleted rows, and resize sort keys to align with common filter columns.- Hot nodes / disk capacity issues: check SVV_DISKUSAGE, re-balance by resizing cluster (resize or add nodes) or unload/load to redistribute.Follow-up actions- Re-run the query with EXPLAIN (or SVL_QUERY_REPORT) after changes to confirm reduced blocks_scanned, cpu_time, and no disk spill.- Implement monitoring of stats_off, disk usage, longest-running queries in daily alerts and automate ANALYZE/VACUUM for high-change tables.This process isolates whether the issue is planner (stats/keys), execution (memory/IO/spill), or infrastructure (skew/disk). For each diagnosed cause implement targeted remediation and validate with before/after metrics (elapsed, cpu_time, blocks_scanned, peak_memory).