One Redshift node pegs at 100% while the others idle — how do you diagnose distribution skew?
answer
- A step finishes only when its slowest slice does
- Look at rows per slice, not rows per table
- One system view gives you the ratio directly
- Sentinel values and NULLs all hash together
- Not every hot node is a placement problem
basics
~20 sCheck per-table row balance across slices with the skew_rows column of SVV_TABLE_INFO, and block counts per slice in STV_BLOCKLIST. A DISTKEY on a lumpy or NULL-heavy column sends most rows to one slice, so the whole query runs at that slice's pace.
solid answer
~50 sRedshift executes each step in parallel across slices and cannot finish a step until its slowest slice does, so one overloaded slice caps the whole query. Start at the table level: `SVV_TABLE_INFO` reports `diststyle` and `skew_rows`, the ratio of rows on the fullest slice to the emptiest. A value near 1 is healthy; a large ratio names your culprit. Confirm physically with per-slice block counts from `STV_BLOCKLIST` for that table id. The usual cause is a `DISTKEY` on a column with a dominant value — a default tenant id, a sentinel like `-1`, or a large block of NULLs, all of which hash to a single slice. Fixes, in order of preference: move the DISTKEY to a genuinely uniform, high-cardinality column that is still a join key; switch to `EVEN` if no such column exists; or replicate the table with `DISTSTYLE ALL` if it is small. Rule out the alternatives too — a broadcast join or a spill can load one node without any distribution skew at all.
code
sql · 6 lines-- 1. which tables are unevenly spread across slices?
SELECT "schema", "table", diststyle, tbl_rows,
skew_rows, unsorted, stats_off
FROM svv_table_info
ORDER BY skew_rows DESC NULLS LAST
LIMIT 20;go deeper
Know that Redshift rows are placed on slices by the distribution key and that an uneven split makes one slice do most of the work.
Explain why the slowest slice sets query time, and name what makes a DISTKEY column lumpy — NULLs, sentinels, dominant entities and low cardinality.
Run the investigation end to end: read SVV_TABLE_INFO and STV_BLOCKLIST, find the offending value, choose between a new DISTKEY, EVEN and ALL, and rule out broadcasts and spills first.
Own the prevention side — how key choices are reviewed before tables ship, what skew monitoring runs continuously, and how you decide that a schema-wide redesign is cheaper than another round of tuning.
## Why one busy slice ruins the query A Redshift cluster runs each plan step in parallel across every slice on every compute node. A step is complete only when the last slice finishes it. If one slice holds ten times the rows of its peers, it spends ten times as long on the scan, and the other slices sit idle waiting. Total elapsed time is set by the straggler, so the cluster's effective parallelism collapses toward one. That is the shape you see on the monitoring graph: a single node at 100% CPU or disk while the rest are flat. It is one of the most recognisable Redshift failure modes and a standard interview scenario. ## Step 1 — find the skewed table `SVV_TABLE_INFO` is the first stop. Per table it reports the distribution style, the sort key, size, and crucially `skew_rows` — the ratio between the number of rows on the slice holding the most and the slice holding the fewest. A ratio close to 1.0 means rows are evenly spread. A ratio of 4, or 40, points straight at the problem table. The same view carries `unsorted` and `stats_off`, which are worth reading at the same time since disorder and stale statistics often accompany a badly chosen key. ```sql SELECT "schema", "table", diststyle, tbl_rows, skew_rows, unsorted, stats_off FROM svv_table_info ORDER BY skew_rows DESC NULLS LAST; ``` ## Step 2 — confirm physically Row counts are logical; blocks are what actually get read. `STV_BLOCKLIST` records one row per 1 MB block with its table id and slice, so grouping by slice for the table in question shows the real storage imbalance. If one slice owns most of the blocks, the diagnosis is settled. ## Step 3 — find the offending value Skew almost always traces to a value distribution problem in the DISTKEY column. Group the table by its DISTKEY and look at the top values by count. The recurring offenders: - **NULL.** All NULLs hash to one slice. A column that is 30% NULL puts 30% of the table on one slice. - **Sentinels.** `-1`, `0`, `'UNKNOWN'`, `'N/A'` used as the unmatched-dimension placeholder behave exactly like NULL. - **A genuinely dominant entity.** One tenant, one merchant or one device that accounts for a large share of all rows. - **Low cardinality.** Distributing on `country_code` across a cluster with many slices leaves most slices empty and a few overloaded, however uniform the data feels. ## Step 4 — fix it In rough order of preference: 1. **Move the DISTKEY** to a column that is both a real join key and uniformly distributed with high cardinality — often a transaction or order id rather than a customer or tenant id. You lose co-location on the old join and gain it on the new one; measure which join actually moves more data. 2. **Switch to `DISTSTYLE EVEN`.** Round-robin placement makes skew impossible. You give up co-location and accept redistribution on joins, which is frequently the better trade when the alternative is a straggler slice on every query. 3. **Use `DISTSTYLE ALL`** if the table is small enough to replicate. Skew disappears and joins become local, at the cost of storage times node count and slower writes. 4. **Change the data.** If the sentinel value is an artefact of the ETL, sometimes the right answer is to stop writing it — or to split the dominant key's rows out into their own handling path. All of these are in-place operations: `ALTER TABLE tbl ALTER DISTSTYLE EVEN` and its KEY/ALL/AUTO variants rewrite the table in the background rather than requiring an unload and reload. ## Step 5 — rule out the imposters Not every hot node is distribution skew. Before reshaping a table, check whether the query is: - **Broadcasting a large table.** A `DS_BCAST_INNER` in the plan loads every node with a full copy; the symptom can look like imbalance if one node is otherwise busy. - **Spilling to disk.** A hash or sort step that exceeds its memory grant writes to disk on the slices that overflow, which is a memory-allocation problem, not a placement problem. - **Suffering sort-key skew rather than row skew.** `SVV_TABLE_INFO` also exposes a sort-key skew indicator; a badly chosen sort key produces unbalanced block sizes without unbalanced row counts. - **Hitting a single-slice step.** Some operations, such as building a small result on the leader or a `LIMIT` after a merge, are simply not parallel. The discipline is the same as any performance investigation: confirm the symptom in the system views before changing a schema, and re-measure the same query after the change rather than trusting that the ratio improved.
- What value of skew_rows in SVV_TABLE_INFO should worry you?It is a ratio of the fullest slice's row count to the emptiest, so 1.0 is perfect balance. Anything close to 1 is fine; a small multiple is worth noting on a large table, and a large multiple on a table that appears in hot queries is a clear defect. Judge it against table size — skew on a tiny table costs nothing.
- Why can a low-cardinality DISTKEY cause skew even when the values are evenly spread?Rows are placed by hashing the value onto a slice, so a column with fewer distinct values than the cluster has slices can only ever occupy that many slices — the rest stay empty. Distributing on something like a country code across a wide cluster wastes most of the available parallelism regardless of how balanced the counts are.
- How would you distinguish distribution skew from a query spilling to disk?Skew shows up in stored data: SVV_TABLE_INFO reports a high skew_rows and STV_BLOCKLIST shows unbalanced block counts, and it affects every query touching that table. A spill is per-query and memory-driven — the execution-time views show a step writing to disk — and it disappears when the step gets more memory or the input shrinks.
- After changing a DISTKEY, what do you measure to confirm the fix?Re-check skew_rows for the table, then re-run the representative queries and compare both elapsed time and the plan's distribution labels. A DISTKEY change often trades a broadcast for a redistribution somewhere else, so confirming the whole workload improved matters more than confirming the ratio moved.
saying these in an interview costs you the question
- Blaming cluster size for a hot node without checking per-slice distribution
- Thinking a sort key can rebalance rows across slices
- Ignoring NULLs and sentinel values as a skew source
- Assuming skew requires unloading and reloading the table to fix
- Choosing a low-cardinality column as DISTKEY because its counts look even