我正在开发一个中型 Web 应用程序,用于处理项目、发票等。 每当我按主题的子字符串进行过滤时,我都很难优化项目列表的过滤查询。有时它会搜索长达一整分钟 - 我的 azure 应用程序中的 DTU 会飙升至 100%。
这是 LINQ 查询:
if (!Filter.Client.IsNullOrEmpty())
{
var searchedTerm = Filter.Client;
query = query.Where(p =>
p.AddressBookLinkage
.Any(linkage => (linkage.MainContactId == null
? linkage.MainSubject.Name
: linkage.MainContact.Name).Contains(searchedTerm)));
var sqlQuery = query.ToList();
}
AddressBookLinkage 保存主题 ID 或联系人 ID。每个项目只包含其中一个,另一个为空。
这是处理此列上的过滤器的子查询生成的 SQL
SELECT 1
FROM [AddressBookProjectLinkages] AS [a]
LEFT JOIN [Subjects] AS [s] ON [a].[MainSubjectId] = [s].[Id]
LEFT JOIN [Contacts] AS [c] ON [a].[MainContactId] = [c].[Id]
WHERE ([p].[Id] = [a].[ProjectId]) AND ((@__searchedTerm_2 LIKE N'') OR (CHARINDEX(@__searchedTerm_2, CASE
WHEN [a].[MainContactId] IS NULL THEN [s].[Name]
ELSE [c].[Name]
END) > 0)))
ORDER BY [p].[Id]
我认为值得一提的是,由于某种原因,这个过滤器在我的本地环境中运行比在生产环境中(使用生产数据)运行得流畅得多。包括 SQL Server 的 Web 应用程序在 Azure 服务上运行。然而,我可以看到如此显着的性能差异只发生在这个过滤器上。
出现的另一个问题是我的 Azure SQL 服务器计划是否足够。我使用具有 10 个 DTU 的标准层。仅使用约 275 MB 的数据库空间。
这是一种猜测,但我认为你可以尝试这样重写
.Where(p => searchedTerm == "" || EF.Functions.Like(something, $"%{searchedTerm}%"))
因此,如果 searchterm 是“”,则不会生成 SQL,否则您将使用类似的内容而不是 charindex。