Skip to content
New issue

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

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

Already on GitHub? # to your account

Query Translation: difference between x.Count()==0 and !x.Any() #27953

Open
Tracked by #30173
sa-es-ir opened this issue May 5, 2022 · 1 comment
Open
Tracked by #30173

Query Translation: difference between x.Count()==0 and !x.Any() #27953

sa-es-ir opened this issue May 5, 2022 · 1 comment

Comments

@sa-es-ir
Copy link

sa-es-ir commented May 5, 2022

I have a performance issue with EF and translated query
With this code

  var result1 = await DbContext.Set<Transaction>()
                .AsNoTracking()
                .GroupBy(x => x.CustomerId)
                .Select(x => new
                {
                    CustomerId = x.Key,
                    avg = x.Count() == 0 ? 0 : EF.Functions.DateDiffDay(x.Min(m => m.TransactionDate), x.Max(m => m.TransactionDate)) / x.Count()
                }).ToListAsync(cancellationToken);

And the translated query is like:

SELECT [t].[CustomerId], CASE
    WHEN COUNT(*) = 0 THEN 0
    ELSE DATEDIFF(day, MIN([t].[TransactionDate]), MAX([t].[TransactionDate])) / COUNT(*)
END AS [avg]
FROM [Transactions] AS [t]
GROUP BY [t].[CustomerId]

Execution Time:

 SQL Server Execution Times:
   CPU time = 125 ms,  elapsed time = 325 ms.

But for this code

 var result2 = await DbContext.Set<Transaction>()
                .AsNoTracking()
                .GroupBy(x => x.CustomerId)
                .Select(x => new
                {
                    CustomerId = x.Key,
                    avg = !x.Any() ? 0 : EF.Functions.DateDiffDay(x.Min(m => m.TransactionDate), x.Max(m => m.TransactionDate)) / x.Count()
                }).ToListAsync(cancellationToken);

And the translated query:

SELECT [t].[CustomerId], CASE
    WHEN NOT (EXISTS (
        SELECT 1
        FROM [Transactions] AS [t0]
        WHERE [t].[CustomerId] = [t0].[CustomerId])) THEN 0
    ELSE DATEDIFF(day, MIN([t].[TransactionDate]), MAX([t].[TransactionDate])) / COUNT(*)
END AS [avg]
FROM [Transactions] AS [t]
GROUP BY [t].[CustomerId]

Execution Time:

 SQL Server Execution Times:
   CPU time = 266 ms,  elapsed time = 401 ms.

I think both of them should be a same query.

Include provider and version information

EF Core version: 6.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0

@sa-es-ir sa-es-ir changed the title Query Translation: different between x.Count()==0 and !x.Any() Query Translation: difference between x.Count()==0 and !x.Any() May 5, 2022
@ajcvickers ajcvickers added this to the Backlog milestone May 7, 2022
@fschlaef
Copy link

Same issue on 3.x branch, except Any() gives a query that takes over 1 minute to execute, while Count != 0 takes under 200ms in our case.

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

3 participants