Linq 进行非常低效的 Entity Framework 查询
Linq making very inefficient Entity Framework query
Entity Framework 为以下 LINQ 查询生成性能非常差的 SQL:
var query = _context.Sessions
.Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
.Select(s => s.Device.User)
.Distinct();
生成这个 SQL:
exec sp_executesql N'SELECT
[Distinct1].[Id] AS [Id],
[Distinct1].[Email] AS [Email],
[Distinct1].[Sex] AS [Sex],
[Distinct1].[Age] AS [Age]
FROM ( SELECT DISTINCT
[Extent4].[Id] AS [Id],
[Extent4].[Email] AS [Email],
[Extent4].[Sex] AS [Sex],
[Extent4].[Age] AS [Age]
FROM (SELECT [Extent1].[OrganizationId] AS [OrganizationId], [Extent3].[UserId] AS [UserId1]
FROM [dbo].[Sessions] AS [Extent1]
INNER JOIN [dbo].[Devices] AS [Extent2] ON [Extent1].[DeviceId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Devices] AS [Extent3] ON [Extent1].[DeviceId] = [Extent3].[Id]
WHERE [Extent2].[UserId] IS NOT NULL ) AS [Filter1]
LEFT OUTER JOIN [dbo].[Users] AS [Extent4] ON [Filter1].[UserId1] = [Extent4].[Id]
WHERE [Filter1].[OrganizationId] = @p__linq__0
) AS [Distinct1]',N'@p__linq__0 int',@p__linq__0=2
我实际要执行的 SQL 下面是运行速度极快的
select distinct u.*
from Sessions s
inner join Devices d on s.DeviceId = d.Id
inner join Users u on d.UserId = u.Id
where OrganizationId = 2
如何让 Entity Framework 生成的 SQL 尽可能接近此查询?
如果您只想要电子邮件,为什么 select 整个 User
实体?
试试这个:
var query = _context.Sessions
.Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
.Select(s => s.Device.User.Email)
.Distinct();
尝试从用户 table:
开始
var query = (
from u in _context.Users
where u.Devices.Any(d => d.Sessions
.Any(s => s.OrganisationId == orgId)
)
select u
);
它不会执行您指定的查询,但它所做的return可能具有同样好的性能。
你可以很简单地做到这一点:
_context.Sessions
.Where(s => s.OrganizationId == 2)
.Select(s => s.Device.User)
.Distinct();
您不需要检查 null
,因为它会为您执行 INNER JOIN
。
我不喜欢使用 DISTINCT ,如果查询包含它则查询错误。
其他方法
var query = _context.Sessions.Include("Device.User.Email")
.Where(s => s.OrganizationId == orgId);
Entity Framework 为以下 LINQ 查询生成性能非常差的 SQL:
var query = _context.Sessions
.Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
.Select(s => s.Device.User)
.Distinct();
生成这个 SQL:
exec sp_executesql N'SELECT
[Distinct1].[Id] AS [Id],
[Distinct1].[Email] AS [Email],
[Distinct1].[Sex] AS [Sex],
[Distinct1].[Age] AS [Age]
FROM ( SELECT DISTINCT
[Extent4].[Id] AS [Id],
[Extent4].[Email] AS [Email],
[Extent4].[Sex] AS [Sex],
[Extent4].[Age] AS [Age]
FROM (SELECT [Extent1].[OrganizationId] AS [OrganizationId], [Extent3].[UserId] AS [UserId1]
FROM [dbo].[Sessions] AS [Extent1]
INNER JOIN [dbo].[Devices] AS [Extent2] ON [Extent1].[DeviceId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Devices] AS [Extent3] ON [Extent1].[DeviceId] = [Extent3].[Id]
WHERE [Extent2].[UserId] IS NOT NULL ) AS [Filter1]
LEFT OUTER JOIN [dbo].[Users] AS [Extent4] ON [Filter1].[UserId1] = [Extent4].[Id]
WHERE [Filter1].[OrganizationId] = @p__linq__0
) AS [Distinct1]',N'@p__linq__0 int',@p__linq__0=2
我实际要执行的 SQL 下面是运行速度极快的
select distinct u.*
from Sessions s
inner join Devices d on s.DeviceId = d.Id
inner join Users u on d.UserId = u.Id
where OrganizationId = 2
如何让 Entity Framework 生成的 SQL 尽可能接近此查询?
如果您只想要电子邮件,为什么 select 整个 User
实体?
试试这个:
var query = _context.Sessions
.Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
.Select(s => s.Device.User.Email)
.Distinct();
尝试从用户 table:
开始var query = (
from u in _context.Users
where u.Devices.Any(d => d.Sessions
.Any(s => s.OrganisationId == orgId)
)
select u
);
它不会执行您指定的查询,但它所做的return可能具有同样好的性能。
你可以很简单地做到这一点:
_context.Sessions
.Where(s => s.OrganizationId == 2)
.Select(s => s.Device.User)
.Distinct();
您不需要检查 null
,因为它会为您执行 INNER JOIN
。
我不喜欢使用 DISTINCT ,如果查询包含它则查询错误。
其他方法
var query = _context.Sessions.Include("Device.User.Email")
.Where(s => s.OrganizationId == orgId);