skip to content

A job spends most of its time in a step whose body the engine cannot read. Which structural changes reduce that cost without rewriting the body?

level: seniorimportance: must knowfreq 58%

answer

  1. supply by hand what the engine cannot deduce
  2. narrow before, not after
  3. named fields beat the whole record
  4. move the readable parts out
  5. change position to change call count

basics

~20 s

Do by hand what the engine cannot deduce: apply the conditions and select the fields before the step, hand the body named fields instead of the whole record, move the parts expressible as named operators out of the body, and call it after a reduction rather than on every raw record.

solid answer

~50 s

The engine will not narrow anything around a body it cannot look inside, so the author supplies the narrowing. Four moves, in order of usual payoff. **One**, place the conditions and the field selection *before* the step, so it sees fewer and smaller records — the engine could not prove this was safe; you can. **Two**, hand the body the named fields it needs rather than the whole record, which lets the read be narrowed again above it. **Three**, split the body: whatever is expressible as named operators moves out and becomes rewritable, leaving only the genuinely custom residue unreadable. **Four**, change how often it is called — after a grouping or a deduplication rather than once per raw record, where the semantics allow. Only then is making the body itself faster the right move. In a model that rewrites nothing for anyone, these were always the author's job.

go deeper

for a junior

Recall the simplest version: filter and select the columns you need before the step, not after it, because the engine will not move them for you across code it cannot read.

for a middle

Explain why each move works: the argument list is the rewriter's only visibility, the position sets the call count, and splitting the body returns part of it to the vocabulary the engine understands.

for a senior

Diagnose before acting. Match the symptom — every column read, call count near the row count, a cheap body that still dominates — to the move, and state the semantic proof you are taking on when you reduce the calls.

for a principal

Decide the convention: what author-written bodies may be handed, whether a second runtime is supported at all, and whether the organisation pays for this in every job or fixes it once in the authoring guidance.

## Why the author has to do this An **opaque step** is a step whose body is ordinary code the **plan rewriter** — the engine component that edits the declared graph into an equivalent, cheaper graph before running it — cannot look inside, so it can only be called, never reasoned about. Every rewrite that would have narrowed the work around that step needed a fact the body does not supply: which fields it reads, whether skipping a call is safe, what it costs. The engine therefore does the only safe thing and runs the graph as written. That is the whole reason this is an author's job. Nothing here is clever; it is supplying by hand the facts the engine could not deduce. ## The four moves, in order 1. **Put the narrowing before the step.** Apply the conditions and select the fields *above the read and below the body*, in the graph as written. The step then sees fewer records and smaller ones. This is the move with the largest payoff on a wide input and the one candidates most often skip, because they are waiting for the engine to do it. 2. **Hand the body named fields, not the whole record.** The argument list is the only visibility the rewriter has. Naming two fields instead of passing a record restores read-time column narrowing — the rewrite that tells the read to produce only the columns some later step uses — for everything the body does not name. 3. **Split the body.** Most author-written bodies are a small custom core wrapped in work the engine already understands: a comparison, an arithmetic expression, a null check, a string operation. Express those as named operators and only the core stays unreadable. What moved out becomes reorderable, narrowable, and collapsible into a single pass over each record with its neighbours. 4. **Change the call count.** The body is called once per record arriving at its position, so move the position. Calling it after a grouping, after a deduplication of distinct inputs, or on one row per key instead of every row can cut calls by orders of magnitude. This is only valid where the semantics allow it — a body that must see every record cannot be moved above a reduction — and it is the move most likely to change results if applied carelessly. Only after those is *making the body faster* the right lever, and it is the most expensive one: it means changing code somebody owns and tests. ## How to tell which one you need | symptom | likely move | |---|---| | the read produces every column although the job outputs four | move 2, then move 1 | | the call count is close to the input row count and the output is tiny | move 1, then move 4 | | the body is twenty lines of which three are custom | move 3 | | the body is cheap but the step still dominates the time | the cost is the hand-off to another runtime, not the body | | the step's time is proportional to what the body genuinely computes | rewrite the body, or accept the cost | Reading those facts off the engine's own rendering of what it intends to run is a skill of its own, owned by Reading a Job Plan; the point here is which restructuring each fact argues for. ## Two claims that do not travel Be careful with two statements that are true of one engine model and false of another. - **"The engine would have done this for me"** — only on an engine with a rewriter over a declared-operator surface, and only for steps it can read. In the model that runs one grouping step at a time and writes every intermediate to disk before the next begins, essentially nothing is rewritten for anybody, and all four moves were always the author's job. - **"Fewer calls is always safe"** — moving a body above or below a grouping changes what it sees, and if it is not deterministic or has effects outside the job, it changes the outcome too. The engine refused this rewrite for exactly that reason; taking it yourself means taking responsibility for the proof. ## What an interviewer is checking That the candidate treats the unreadable body as a *position in a graph* rather than as a piece of code. The fastest available win almost never involves opening the body: it involves changing what reaches it and how often. A candidate who jumps straight to rewriting the body has not understood why the step was expensive — and one who says "I would let the optimiser handle it" has just told you they do not know what an unreadable body does to an optimiser.

  • Why is placing the conditions before the step something the engine would not do itself?
    Moving a condition earlier changes how many times the body is called. With no proof that the body is free of effects and cannot fail, the engine treats that as a change in behaviour and refuses. The author knows what the body does and can take responsibility for the move.
  • What can go wrong when you move the body to run after a grouping?
    It no longer sees every record. If it was accumulating something, sampling, or emitting effects per record, the result changes. The move is only valid where one call per group is semantically the same as one per record, which is a claim about the body, not about the engine.
  • If the body is cheap and the step is still the slowest, what is left?
    The cost is not the body. Look at the two things that stack on top: the reading the engine could not narrow, and — if the body runs in a language runtime other than the engine's own — a fixed per-record cost of carrying records out and results back, which batching amortises.
  • Does any of this change on an engine that rewrites nothing?
    The moves are identical; only the framing changes. Where no rewriter exists — the model that runs one grouping step at a time, writing every intermediate to disk — nothing was ever going to be narrowed on the author's behalf, so writing the conditions and the field selection early is simply how jobs are written there.

saying these in an interview costs you the question

  • Reaches for rewriting the body before changing what reaches it
  • Says the optimiser will push the conditions down anyway
  • Moves the body above a grouping without checking the semantics
  • Thinks passing the whole record is equivalent to naming fields
  • Assumes every engine would have narrowed the read for them