gortiz opened a new issue, #19815: URL: https://github.com/apache/pinot/issues/19815
In the multi-stage engine, `FunctionOperand.apply` evaluates its operands and invokes the function for every input row. `TransformOperandFactory` creates a `FunctionOperand` for every function call, even when all its operands are literals, so a call like `f(1, 2)` runs again on each row. Most of the time this does not matter, because `PinotEvaluateLiteralRule` folds deterministic calls on literals at the broker, so they reach the workers as a `LiteralOperand`. But some calls are better left unfolded. In #19552 I'm marking `generateArray` as not foldable. Folding serializes the whole sequence, up to 100,000 elements, into the plan sent to every worker of the stage, while the workers only need the three arguments to generate it. The catch is that a call like this is now evaluated once per row whenever it runs in an intermediate stage: ```sql SELECT a.id, generateArray(0, 99999) FROM a JOIN b ON a.id = b.id ``` The projection sits above the join, so it runs in the join's stage, and each joined row rebuilds a 100,000 element array that is the same every time. An uncorrelated `CROSS JOIN UNNEST(generateArray(...))` is not affected, because the planner puts the call in its own single-row Values stage. Leaf stages are fine: there the call goes through `GenerateArrayTransformFunction`, which `TransformFunctionFactory` shares per query context, so it is computed once per server. I suggest that `FunctionOperand` caches its result when every operand is a `LiteralOperand` and the function is `FunctionVolatility.IMMUTABLE`. Checking volatility instead of `FunctionInfo.isDeterministic()` matters here, because `generateArray` reports itself as non-deterministic only to opt out of folding. Computing the value lazily on the first `apply` keeps argument errors where they surface today, at execution time, and avoids computing results that are never used. The cached value is returned to every caller, so callers must not mutate it, which is the same contract `LiteralOperand` already has. This helps any function on literal arguments that is not folded, not only `generateArray`. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
