UNeverNo
UNeverNo

Reputation: 583

EF Core performs poorly although generated SQL from ToQueryString() is lightning fast

I've got the following query:

var query = context.Set<TEntity>()
    .AsNoTracking()
    .Where(x => ids.Contains(x.Id1) && x.Id2 != x.Id1 && (x.Status != "Status" || x.Status == null))
    .OrderBy(x => x.Field1)
    .Take(10);

ids is of type IEnumerable<Guid?>

If I perform a Count() before order and top, result is back in 400ms. If I however perform a ToList() after order and top it takes more than 30s.

That's the generated sql from ToSqlQuery():

DECLARE @__p_1 int = 10;
DECLARE @__ids_0 nvarchar(4000) = N'["890217ea-ad02-4b9f-9f9d-734a72e9fb04"]';

SELECT TOP(@__p_1) [w].*
FROM [TEntity] AS [w]
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON(@__ids_0) WITH ([value] uniqueidentifier '$') AS [m]
    WHERE [m].[value] = [w].[Id1] OR ([m].[value] IS NULL AND [w].[Id1] IS NULL)) AND ([w].[Id2] <> [w].[Id1] OR [w].[Id1] IS NULL) AND ([w].[Status] <> 'Status' OR [w].[Status] IS NULL OR [w].[Status] IS NULL)
ORDER BY [w].[Field1]

If I run it manually in Azure Data Studio I get the result in less than 1 second.

Edit: I analyzed the issue further by intercepting the generated queries from ef core and found out, that they are related to 'exec sp_executesql' slowing down the query.

exec sp_executesql N'SELECT TOP(@__p_1) [w].*
FROM [TEntity] AS [w]
WHERE EXISTS (
    SELECT 1
    FROM OPENJSON(@__ids_0) WITH ([value] uniqueidentifier ''$'') AS [m]
    WHERE [m].[value] = [w].[Id1] OR ([m].[value] IS NULL AND [w].[Id1] IS NULL)) AND ([w].[Id2] <> [w].[Id1] OR [w].[Id1] IS NULL) AND ([w].[Status] <> ''Status'' OR [w].[Status] IS NULL OR [w].[Status] IS NULL)
ORDER BY [w].[Field1]',N'@__p_1 int,@__ids_0 nvarchar(4000)',@__p_1=10,@__ids_0=N'["890217ea-ad02-4b9f-9f9d-734a72e9fb04"]'

Any idea what's going on here?

Edit2: After checking sp_executesql, I found out, that there are more people having the same issue: Major performance difference between Entity Framework generated sp_executesql and direct query in SSMS

I ended up implementing a custom DbCommandInterceptor, that injects my desired sql (OPTION (OPTIMIZE FOR UNKNOWN)), when I tag a query with an extension method.

Upvotes: 0

Views: 42

Answers (0)

Related Questions