Which properties of the branch above a step make recomputing it cheaper than keeping its result pinned in worker memory?
answer
- price both sides, not one
- narrow chain over a durable source
- a wide step is the multiplier
- some sources cannot be re-read identically
- re-read charges and changing sources
basics
~20 sRecomputation is cheap when every step in the branch is computed locally over a durable, re-readable source. It gets expensive when the branch crosses a step needing records from other workers, or reads a source that cannot be read twice identically.
solid answer
~50 sCompare two costs, not one. The pin side is bytes held per worker, in whatever form the engine keeps them, for as long as they are held — and the operator working memory that displaces. The recompute side is the branch walked again, `n - 1` extra times. That walk is cheap when every step in it is narrow — computable by each worker from records it already holds — and the source is a durable file set the engine can re-read identically, especially where a selective filter means little data survives the walk. It is expensive when the branch crosses a **wide step**, one that cannot be computed from records a worker already holds, so every worker writes its output split by destination and every worker fetches its share; when the branch does heavy per-record work; or when the source cannot be read twice the same way — a changing operational store, a per-read charge, or anything time-dependent inside the branch.
go deeper
Know that recomputing a branch means running every step in it again from the source, and that how expensive that is depends on what those steps do.
Explain why a step needing records from other workers is categorically more expensive to repeat than a step each worker computes from what it already holds, and price both sides of the trade.
Show judgment: measure the branch from the run's own numbers, weigh the pinned copy against the operator working memory it displaces, and recognise the source that cannot be read twice the same way as a correctness problem rather than a cost one.
Set the guidance the team applies without measuring every time — when a branch earns a pin, when it should instead be written out to durable storage, and who absorbs the cost when a pinned copy displaces other work on a shared pool.
## The trade has two sides, and most candidates only price one The usual mistake is to price the recompute and call the pin free. Both sides have a number: - **The pin side.** Bytes held per **worker** — one operating-system process on one machine that runs part of the job and owns a fixed amount of memory nothing else can borrow — in whatever form the engine keeps them, multiplied by how long they are held. Its real cost is not the bytes but what they displace: the same budget feeds **operator working memory**, the part operators borrow while sorting, grouping or building a held join side. - **The recompute side.** The branch above the step, walked `n - 1` extra times for `n` readers. Its cost depends entirely on what is in the branch. A decision that only prices one side is how a job ends up slower after an optimisation. ## What makes recomputation cheap 1. **Every step in the branch is narrow** — each worker can compute its share from records it already holds, with no data crossing between workers. A narrow chain is close to a linear scan of the source. 2. **The source is durable and re-readable** — an immutable file set that the engine can read again and obtain the same records. 3. **The branch is selective.** A filter that discards most rows means the walk reads a lot and produces little, so the thing you would have pinned is small — but by the same token, so is the saving. Selectivity cuts both sides; what matters is that the read is sequential and cheap. 4. **Per-record work is trivial** — projections, simple predicates, type conversions. Under those conditions the recompute is often within noise of the read you were going to do anyway, and the pin's displacement is the only thing you have actually changed. ## What makes recomputation expensive 1. **The branch crosses a wide step** — a step that cannot be computed from records one worker already holds, so every worker writes its output split by destination and every worker fetches its share. This is the single biggest multiplier: repeating it repeats a network exchange, the write and read of intermediate data, and the waiting that a synchronisation point between the two phases imposes. 2. **Heavy per-record work** — parsing, decompression, calls out to another service, expensive user-supplied functions. These scale with rows read, and the walk reads all of them again. 3. **A wide fan-in.** A branch that joins several large inputs pays for all of them on every walk. 4. **The source cannot be read twice the same way** (see below), which makes the recompute not merely expensive but wrong. | property of the branch | effect on the recompute | leans toward | |---|---|---| | all steps narrow, durable file source | roughly one extra scan | recompute | | selective filter early | small result, cheap walk | recompute | | crosses a wide step | repeats an exchange and its synchronisation point | pin | | expensive per-record work | scales with rows, paid every walk | pin | | source not re-readable identically | recompute may change the answer | pin, or write it out | ## Sources that cannot be read twice the same way This is the case that turns a performance question into a correctness one. Examples, none of which require naming a product: - **A live operational store.** The branch queries a database that other writers are changing. Two walks return two different sets, so two readers of the "same" intermediate disagree. - **A source charged per read or per byte scanned.** The second walk is not slower, it is billed again. - **A source that can only be consumed once**, or that must be re-positioned to be re-read at all. - **Anything time-dependent or random inside the branch** — a current-time predicate, a sampling step, an identifier drawn at random. The two walks legitimately differ. When the branch has this property, the choice is not pin-against-recompute; it is **pin, or write the intermediate out to durable storage and read it back as a source**. Writing it out costs more than pinning but survives everything and is re-readable by definition. ## What varies between engines - Some engines treat a pin as a guarantee and will overflow the copy to **local scratch disk** — disk attached to the worker whose contents nobody may read after the job — rather than drop it. Others treat it as a request and will drop a pinned result to make room for operator work, recomputing the branch on the next read. On the second kind, the recompute cost you priced is not hypothetical — it is what you will actually pay, intermittently. - Some engines re-plan mid-run from what they measured, which changes the shape of the branch between two walks; go no further than knowing that some do. - On the oldest two-phase disk-to-disk model in this family, intermediates are written between phases whether or not you asked, so the question presents differently: it is whether to read a written output again, not whether to hold anything. ## How to actually decide Measure the branch once, from **the run's reported numbers** — whatever the engine reports per unit of work after a run: how long it took, how many bytes it read, whether a wide step is inside it. Then measure the pin's displacement by watching whether the steps after it begin spilling — writing part of their working set out to local disk because it no longer fits. Two runs answer this far better than any rule of thumb, and the rule of thumb that survives is narrow: **pin when the branch crosses a wide step and is read more than once; otherwise start by not pinning.**
- The branch reads a live operational store that other writers are changing. What changes about the decision?It stops being a performance trade. Two walks of that branch can return different records, so two readers of the same named intermediate would disagree with each other. Either keep one computed copy so both readers see the same records, or write the intermediate out to durable storage and read it back as a source — which costs more than holding it but is re-readable by definition and survives worker loss.
- The branch is cheap to recompute but its result is tiny. Is pinning it harmless?Close to harmless, and also close to pointless. A small copy displaces little operator working memory, so the downside is small — but the saving is equally small, because a cheap narrow walk over a durable source is roughly one extra scan. The cost that remains is bookkeeping and the risk that the pin is never released and accumulates with others like it.
- Why does a wide step inside the branch weigh so heavily on this decision?Because repeating it repeats far more than compute. Every worker writes its output split by destination, every worker fetches its share across the network, and the second phase cannot start until the first has finished producing — so the whole job waits at that point again. That is categorically more expensive than repeating a scan, which is why a branch containing one is the clearest case for keeping the result.
saying these in an interview costs you the question
- Recomputing is always more expensive than holding the result
- Pinning is free once the memory has already been allocated
- A branch is a branch — the steps inside it do not change the cost
- Any source can simply be read again to rebuild the result
- Pinning fixes a branch whose two walks return different records