Skip to content

Optimize array_has when the search element is a column #23334

Description

@freakyzoidberg

Description of performance issue

array_has(array, element) returns, for each row, whether array contains element.

When element is a scalar literal, DataFusion has a fast path (added in #20374). But when element is an column, e.g. array_has(t1.tags, t2.key) used as a join filter, execution goes through array_has_dispatch_for_array (the ColumnarValue::Array needle branch in datafusion/functions nested/src/array_has.rs).

That branch compares each row by invoking the Arrow eq comparison kernel once per row.
Every invocation allocates a BooleanArray and pays downcast + dispatch overhead, so for an N-row batch it is N kernel calls and N allocations, the cost is dominated by fixed per-row overhead, not the element comparison itself.

This is a common shape in real workloads: matching tags/labels/keys between two tables lowers to an array-needle array_has join filter (e.g. a NestedLoopJoinExec with filter=array_has(tags, key)). It was a visible fraction of one such profile even after the join's deep-copy was fixed in #18070 / #18161.

Image

Describe the solution you'd like

Performance improvement for at least primitives, non-nulls, and/or more

Proposition/draft of improvement

PR with bench: #23335
PR with perf and bench results: #23337 (leaving on draft until get agreement that this should be optimised)

Additional context

Related: #20374, #18070 / #18161, #18727.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions