Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Join with query filter causes nested subquery and poor query performance #21082

Closed
bigpjo opened this issue May 29, 2020 · 5 comments
Closed

Comments

@bigpjo
Copy link

bigpjo commented May 29, 2020

EFCore 3.1.4

When using dynamic query filters and joins the sql generated uses subqueries for each table joined causing slow query executing on large data tables.

namespace EFCoreTest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new EFExampleContext())
            {
                var cd = (from n in db.Name
                          join t in db.Telephone on n.Id equals t.NameId
                          select new
                          {
                              n.Name1,
                              t.PhoneNumber
                          })
                         .ToList();
            }
        }
    }

    public class EFExampleContext : DbContext
    {
        public EFExampleContext()
        {
        }

        public virtual DbSet<Name> Name { get; set; }
        public virtual DbSet<Telephone> Telephone { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Database=EFExample;Integrated Security=true;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Name>(entity =>
            {
                entity.Property(e => e.Id).ValueGeneratedNever();

                entity.Property(e => e.Name1)
                    .HasColumnName("Name")
                    .HasMaxLength(100)
                    .IsUnicode(false);
            });

            modelBuilder.Entity<Telephone>(entity =>
            {
                entity.Property(e => e.Id).ValueGeneratedNever();

                entity.Property(e => e.PhoneNumber)
                    .HasMaxLength(10)
                    .IsUnicode(false);

                entity.HasOne(d => d.Name)
                    .WithMany(p => p.Telephone)
                    .HasForeignKey(d => d.NameId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Telephone_Telephone");

                entity.HasQueryFilter(e => !e.Deleted);
            });


        }

    }

    public class Name
    {
        public Name()
        {
            Telephone = new HashSet<Telephone>();
        }

        public int Id { get; set; }
        public string Name1 { get; set; }
        public bool Deleted { get; set; }

        public virtual ICollection<Telephone> Telephone { get; set; }
    }

    public class Telephone
    {
        public int Id { get; set; }
        public int NameId { get; set; }
        public string PhoneNumber { get; set; }
        public bool Deleted { get; set; }

        public virtual Name Name { get; set; }
    }
}

Produces sql statement

SELECT [n].[Name] AS [Name1], [t0].[PhoneNumber]
FROM [Name] AS [n]
INNER JOIN (
    SELECT [t].[Id], [t].[Deleted], [t].[NameId], [t].[PhoneNumber]
    FROM [Telephone] AS [t]
    WHERE [t].[Deleted] <> CAST(1 AS bit)
) AS [t0] ON [n].[Id] = [t0].[NameId]

Whereas the optimal query would be

SELECT [n].[Name] AS [Name1], [t0].[PhoneNumber]
FROM [Name] AS [n]
INNER JOIN [Telephone] AS [t0] ON [n].[Id] = [t0].[NameId] and [t0].[Deleted] <> CAST(1 AS bit)

Any suggestions on what I may be doing wrong or how to optimise the query generation

Thanks in advance

@Coldairarrow
Copy link

is there any solutions ?
i have the same question

@paaland
Copy link

paaland commented Nov 23, 2020

Not only that, but if you try and use full text indexing functions like Contains or FreeText it failes since it tried to do them on the sub query.

SELECT [n].[Name] AS [Name1], [t0].[PhoneNumber]
FROM [Name] AS [n]
INNER JOIN (
    SELECT [t].[Id], [t].[Deleted], [t].[NameId], [t].[PhoneNumber]
    FROM [Telephone] AS [t]
    WHERE [t].[Deleted] <> CAST(1 AS bit)
) AS [t0] ON [n].[Id] = [t0].[NameId]
WHERE  Contains('PhoneNumber', '"something")

@FrancoisKr
Copy link

Will this issue be addressed? Any workarounds?

@roji
Copy link
Member

roji commented Jan 4, 2021

@smitpatel related/dup of #17622?

@smitpatel
Copy link
Member

Also related #21082

@smitpatel smitpatel removed this from the Backlog milestone Jul 13, 2021
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants