Skip to content

merge_insert is loading too many columns during indexed merge insert #3480

Description

@westonpace

We are loading all columns from the target table. We should only need to load the join key columns and/or any columns needed for a filter.

Background

We are migrating from an implementation of merge insert that manually manipulates streams to one that constructs a DataFusion plan and runs optimizers on that plan for optimize it.

The old code path is in execute_uncommitted_impl:

https://github.com/lancedb/lance/blob/94dcaf5e735480f9f61216b4e4f90358dbeac2ba/rust/lance/src/dataset/write/merge_insert.rs#L1337-L1340

While the new codepath is under execute_uncommitted_v2:

https://github.com/lancedb/lance/blob/94dcaf5e735480f9f61216b4e4f90358dbeac2ba/rust/lance/src/dataset/write/merge_insert.rs#L1352-L1371

Task

Goal: use the new code path when has_scalar_index=True.

If the index is up-to-date (no unindexed fragments), the plan should look like:

MergeInsert: on=[key], ...
  ProjectionExec: <assign action>
    AddRowAddrExec: ...
      ScalarIndexJoinExec: on=[key] index=[key_idx]
        StreamingTableExec: ...

Basically, the input should "join" against the index to find which do and don't have _rowids (exist in the dataset). Then we can use AddRowAddrExec to get the addresses.

If the index is not up-to-date, then the plan should be a union of the existing plan plus the indexed one, with an additional filter to ensure we don't duplicate new rows:

MergeInsert: on=[key], ...
  ProjectionExec: <assign action>
    UnionExec:
      AddRowAddrExec: ...
        FilterExec: _rowid is not null
          ScalarIndexJoinExec: on=[key] index=[key_idx]
            ReplayExec: ...
      HashJoinExec: on=[key]
        LanceScan: projection=[key], row_addr=true, ...
        ReplayExec: ...

Note: we have an existing test for query plans here you can imitate: https://github.com/lancedb/lance/blob/94dcaf5e735480f9f61216b4e4f90358dbeac2ba/rust/lance/src/dataset/write/merge_insert.rs#L3001-L3002

TODO

  • Implement ScalarIndexJoinExec
  • Implement ScalarIndexJoinNode (logical plan) with UserDefinedLocalNodeCore trait
  • Implement ExtensionPlanner for ScalarIndexJoin that decides between up-to-date and not up-to-cade plans
  • Update create_plan to handle creation of plan with ScalarIndexJoin

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: highIssues that are high priority (for LanceDb, the organization)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions