Skip to content

SQL-3343: Rework FLATTEN field-access to avoid repeated work#167

Open
jameseh96 wants to merge 2 commits into
mongodb:mainfrom
jameseh96:SQL-3343
Open

SQL-3343: Rework FLATTEN field-access to avoid repeated work#167
jameseh96 wants to merge 2 commits into
mongodb:mainfrom
jameseh96:SQL-3343

Conversation

@jameseh96

@jameseh96 jameseh96 commented Jul 7, 2026

Copy link
Copy Markdown

Previously, algebrize_flattened_field_path was recursive.

For a path a.b.c, the call chain would look like:

algebrize_flattened_field_path(key, [a,b,c])
> construct_field_access_expr( algebrize_flattened_field_path(key,[a,b]), "c" )
  > construct_field_access_expr( algebrize_flattened_field_path(key,[a]), "b" )
      > construct_field_access_expr( algebrize_flattened_field_path(key,[]), "a" )
          > construct_field_access_expr( Reference(key), "a" )

Each construct_field_access_expr call evaluated

FieldAccess{...}.schema(state)

to decide nullability.

FieldAccess::schema is itself recursive: it calls self.expr.schema(), which will call fa.schema(state) on its contents.

The base case Expression::Reference does env.get(key).cloned(), cloning the root schema.

So each layer of construct_field_access_expr would eventually clone the root schema, which could be very large. Further, it would then repeat work done by a lower call:

  1. clone root -> a
  2. clone root -> a -> b
  3. clone root -> a -> b -> c

This could be quite costly.

Change to an iterative approach, tracking the current schema as the call descends through the path.

For the sample_analytics FLATTEN benchmark this cuts the project field-access build from ~11.4s to ~3.3s, -71%.

@jameseh96

Copy link
Copy Markdown
Author

cargo test passes locally, but I'm not familiar with the Atlas SQL workflow.

@mattChiaravalloti mattChiaravalloti left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great idea and a useful change. Everything is passing on evergreen so we should be confident this is as correct as the previous solution. I'm marking this as approved but we'll hold off on merging this until after the team triages the associated ticket later on today.

Comment thread mongosql/src/algebrizer/definitions.rs Outdated
fn build_flattened_field_access(
key: Key,
path: &[String],
root_schema: &crate::schema::Schema,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
root_schema: &crate::schema::Schema,
root_schema: &schema::Schema,

[nit] We already import crate::schema::self at the top of the file, so we should not need to prefix this with crate:: here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread mongosql/src/algebrizer/definitions.rs Outdated
let mut expr = mir::Expression::Reference(mir::ReferenceExpr { key });
// Avoid cloning the (potentially huge) root schema: narrow from a borrow for the first
// field, then from the owned narrowed sub-schema for subsequent fields.
let mut current_schema: Option<crate::schema::Schema> = None;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut current_schema: Option<crate::schema::Schema> = None;
let mut current_schema: Option<schema::Schema> = None;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mattChiaravalloti mattChiaravalloti marked this pull request as ready for review July 7, 2026 17:11
@mattChiaravalloti mattChiaravalloti requested a review from a team as a code owner July 7, 2026 17:11
@mattChiaravalloti

Copy link
Copy Markdown
Collaborator

@jameseh96 The team triaged this and decided to move forward with it. I tagged another team member to give it a second look. When you get 2 approvals and address any outstanding comments, we can get this merged.

It looks like your commits aren't signed, either. If you are able, can you sign the commits and re-push? Feel free to force push the signed commits to this PR when you sign them.

@bucaojit bucaojit left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @jameseh96 .
LGTM

@jameseh96 jameseh96 force-pushed the SQL-3343 branch 2 times, most recently from f5f38c3 to 4bbd2f5 Compare July 9, 2026 17:34
@jameseh96

Copy link
Copy Markdown
Author

Comments addressed, commits signed, re-pushed!

Previously, algebrize_flattened_field_path was recursive.

For a path a.b.c, the call chain would look like:

algebrize_flattened_field_path(key, [a,b,c])
> construct_field_access_expr( algebrize_flattened_field_path(key,[a,b]), "c" )
  > construct_field_access_expr( algebrize_flattened_field_path(key,[a]), "b" )
      > construct_field_access_expr( algebrize_flattened_field_path(key,[]), "a" )
          > construct_field_access_expr( Reference(key), "a" )

Each construct_field_access_expr call evaluated

```
FieldAccess{...}.schema(state)
```

to decide nullability.

FieldAccess::schema is itself recursive: it calls self.expr.schema(),
which will call `fa.schema(state)` on its contents.

The base case Expression::Reference does `env.get(key).cloned()`,
cloning the root schema.

So each layer of construct_field_access_expr would eventually clone the
root schema, which could be very large. Further, it would then repeat
work done by a lower call:

1. clone root -> a
2. clone root -> a -> b
3. clone root -> a -> b -> c

This could be quite costly.

Change to an iterative approach, tracking the current schema as the call
descends through the path.

For the sample_analytics FLATTEN benchmark this cuts the project
field-access build from ~11.4s to ~3.3s, -71%.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants