Query: Be smart about what to store in variables for shaper

Open
#21,336 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
20/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Stale
Tech stack
csharp
Domain
backend, databases

Research direction

Start by reading related issues #21334 and #21335, then trace how ProjectionBindingExpression and the query shaper choose values for client code. The work is done when maximum evaluatable subtrees are stored appropriately, conditional entity materialization avoids unnecessary collections, and repeated entities preserve the required tracking or no-tracking behavior.

Written by the indexing model from the issue text.

Description

area-perf area-query customer-reported

#21334 talks about not generating variables when we don't need to.
#21335 talks about not boxing when we store them

This issue is about being smart about what we store in variables.
Currently we utilize the ProjectionBindingExpression to store in variables while it is generally ok but there are some cases when a different strategy would actually achieve better perf.
Rather than dealing with ProjectionBindingExpression, we could deal with elements which needs to go into client code instead. In order words, we can take maximum subtree we can evaluate before going into client code and store that in variable instead.
One thing it would solve directly is (which has some overlap with #21334) condition ? EntityA : EntityB scneario where we could skip materializing one entity altogether based on how condition evaluates.
Places to identify what to materialize would generally include

  • Top level if projecting a scalar or entity
  • Members of NewExpression (recursive)
  • Members of MemberInitExpression (basically DTOs) (recursive)
  • Arguments being passed to client method or members.

The assumption that maximum subtree would be translated to server remains valid as long as no entities are involved. But with entities the server projection wouldn't be maximum subtree and we need to do that on client side.
A big perf here would be collections when both above entities have collection includes. We could skip materializing and populating whole collection if the entity is not materialized due to the condition. Collection won't be initialized so populate collection should no-op.

A caveat that if the same entity is being reference in multiple spots then we need to make sure we materializes only once. For tracking query it should do identity resolution but no tracking we don't want to create 2 instances.

Dominant language
C#
Stars
14.8k
Forks
3.4k
Avg merge
2d 5h
Merged PRs (30d)
134

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/efcore

All issues in dotnet/efcore

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.