EF Core 查询速度慢。我不知道为什么

问题描述 投票:0回答:1

我将 EF Core 7 与 .NET 6 Blazor Server 应用程序一起使用,我不确定哪里出了问题。数据库表似乎没有按照标准约定正确设置,因此这可能就是我出错的原因。

注意 - 我更改了表名称和列,因此事情可能不明白我为什么要查找某些内容,但只需忽略它并查看结构即可。

我有这两个表,我首先用代码表示。

public class TableA
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string SubName {get; set;}
    public ICollection<TableB> TableBs {get; set;}
}

public class TableB
{
    public long Id { get; set; }
    public string DisplayValue { get; set; }
    public string SearchValue { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public long? AId { get; set; } // this if the foreign key for TableA, the convention of TableAId is not followed here.

    public TableA TableA { get; set; }
}

基本上TableA可以有很多TableB

由于在 TableB 中,FK 并未按照 EF 的预期命名,因此我必须在流畅的验证类中执行此操作(我仅显示相关信息,因此并不完整)

//Fluent Configuration
builder.ToTable("TableA", "schemaName")
builder.HasMany(x => x.TableBs).WithOne(x => x.TableA).HasForeignKey(x => x.AId)

builder.ToTable("TableB", "schemaName")
builder.HasOne(x => x.TableA).WithMany(x => x.TableBs).HasForeignKey(x => x.AId)

现在我想搜索与 TableB 中的“SearchValue”匹配的任何值。

如果输入“Bob”,则应该找到以“Bob”开头的任何内容,例如“Bob Jim”、“Bob Frank”

在 SQL 中我会写这样的东西

 SELECT p.DisplayValue, p.StartDate r.Name, r.SubName
FROM TableB as p INNER JOIN
TableA as r ON p.AId = r.Id
where  p.SearchValue like 'Bob%' and p.EndDate is not null

我正在 SearchValue 上执行类似操作,并检查结束日期是否不为空。

然后我想返回 DisplayValue、开始日期、名称和子名称。

现在在 linq 我有

var results = context.TableB.Include(x => x.TableA).Where(x => x.SearchValue.Contains("Bob") && x.EndDate != null).Select(x = new {
    DisplayValue = x.DisplayValue,
    StartDate = x.StartDate,
    Name = x.TableA.Name,
    SubName = x.TableA.SubName
}).ToList();

这会产生这个sql语句

DECLARE @__SearchValue_0 nvarchar(20) = N'Bob';
SELECT [a].[Name], [a].[SubName], [p].[DisplayValue], [p].[StartDate]
FROM [schemaName].[TableB] as [p]
LEFT JOIN [schemaName].[TableA] AS [a] ON [p].[AId] = [a].[Id]
WHERE ((@__SearchValue_0 LIKE N'') or CHARINDEX(@__SearchValue_0, [p].[SearchValue]) > 0) AND ([p].EndDate IS NOT NULL)

现在我编写的 SQL 查询在不到一秒的时间内返回 10 个结果。 Linq 查询返回 14 个结果,需要 30 秒。

我认为结果差异是因为 contains 与 sql 中的“like”并不相同,我也尝试过 EF.Functions.Like,但它仍然很慢,但确实返回了相同的结果计数。

表 B 有 11,000 条记录,表 A 有 200 条记录。

首先我认为这是因为它决定执行 LEFT JOIN,所以我尝试使用 .JON() 编写查询并强制其进行 INNER JOIN,但它仍然需要 30 秒并返回 14 个结果。

所以我不确定我哪里错了。

如果我将其从 Contains() 更改为 == "Bob",那么查询似乎可以找到关于 EF core 如何构建它的信息,并且结果很快,但当然不正确。

c# sql-server entity-framework entity-framework-core blazor
1个回答
0
投票

首先,这些搜索不一样。但不确定这是否是整个问题。

Where(x => x.SearchValue.Contains("Bob"))

不一样
p.SearchValue like 'Bob%'

更像是

p.SearchValue like '%Bob%'

所以也许可以使用类似的东西

Where(x => x.SearchValue.Substring(1, "Bob".Length) == "Bob")

可能会生成更好的 SQL

(我假设您在实际使用中会在此处使用变量)

© www.soinside.com 2019 - 2024. All rights reserved.