我有一个数据库中大约有 5,000 行。还有许多多对多关系。作为"高级搜索"查询的一部分,我需要跨表进行自由文本搜索。
我创建了一个强类型数据集,并在应用启动时从 SQL Server 导入所有数据。对数据集执行 LINQ 查询时,查询执行速度非常慢(大约 15 秒)。我认为对内存中数据集执行查询会比 SQL Server 快得多,但事实似乎并非如此。我什至需要在 where 子句中添加更多的连接和"搜索",所以事情只会变得更糟。
在我正在搜索的字段中,最长的是摘要,数据库中最长的字段小于 2,000 字节,所以我们不谈论要搜索的大量数据。我在这里吠错了树,还是有办法提高此查询的性能?
代码如下:
var results = from e in _data.ds.Employee
join es in _data.ds.EmployeeSkill on e.EmployeeId equals es.EmployeeId into esGroup from esItem in esGroup.DefaultIfEmpty()
join s in _data.ds.Skill on esItem?.SkillId equals s.SkillId into sGroup from skillItem in sGroup.DefaultIfEmpty()
join er in _data.ds.EmployeeRole on e.EmployeeId equals er.EmployeeId into erGroup from erItem in erGroup.DefaultIfEmpty()
join r in _data.ds.Role on erItem?.RoleId equals r.RoleId into rGroup from rItem in rGroup.DefaultIfEmpty()
join et in _data.ds.EmployeeTechnology on e.EmployeeId equals et.EmployeeId into etGroup from etItem in etGroup.DefaultIfEmpty()
join t in _data.ds.Technology on etItem?.TechnologyId equals t.TechnologyId into tGroup from tItem in etGroup.DefaultIfEmpty()
where
e.FirstName.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
e.LastName.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
e.RMMarket.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
!e.IsSummaryNull() && e.Summary.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0
select new SearchResult
{
EmployeeId = e.EmployeeId,
Name = e.FirstName + " " + e.LastName,
Title = e.Title,
ImageUrl = e.IsImageUrlNull() ? string.Empty : e.ImageUrl,
Market = e.RMMarket,
Group = e.Group,
Summary = e.IsSummaryNull() ? string.Empty : e.Summary.Substring(1, e.Summary.Length < summaryLength ? e.Summary.Length - 1 : summaryLength),
AdUserName = e.AdUserName
};
假设您仍然加载到 DataSet
s 而不是对象列表中(没有足够的信息来翻译该部分),这是我的建议:
预联接要用作搜索索引的数据:
var searchBase = (from e in _data.ds.Employee
join es in _data.ds.EmployeeSkill on e.EmployeeId equals es.EmployeeId into esGroup
from esItem in esGroup.DefaultIfEmpty()
join s in _data.ds.Skill on esItem?.SkillId equals s.SkillId into sGroup
from skillItem in sGroup.DefaultIfEmpty()
join er in _data.ds.EmployeeRole on e.EmployeeId equals er.EmployeeId into erGroup
from erItem in erGroup.DefaultIfEmpty()
join r in _data.ds.Role on erItem?.RoleId equals r.RoleId into rGroup
from rItem in rGroup.DefaultIfEmpty()
join et in _data.ds.EmployeeTechnology on e.EmployeeId equals et.EmployeeId into etGroup
from etItem in etGroup.DefaultIfEmpty()
join t in _data.ds.Technology on etItem?.TechnologyId equals t.TechnologyId into tGroup
from tItem in etGroup.DefaultIfEmpty()
select new {
e.FirstName, e.LastName, e.RMMarket, e.Summary,
e.EmployeeID, e.Title, e.ImageUrl, e.Group, e.AdUserName
}).ToList();
对加载和联接的数据运行搜索:
var results = from e in searchBase
where
e.FirstName.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
e.LastName.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
e.RMMarket.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0 ||
!e.IsSummaryNull() && e.Summary.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0
select new SearchResult {
EmployeeId = e.EmployeeId,
Name = e.FirstName + " " + e.LastName,
Title = e.Title,
ImageUrl = e.IsImageUrlNull() ? string.Empty : e.ImageUrl,
Market = e.RMMarket,
Group = e.Group,
Summary = e.IsSummaryNull() ? string.Empty : e.Summary.Substring(1, e.Summary.Length < summaryLength ? e.Summary.Length - 1 : summaryLength),
AdUserName = e.AdUserName
};
顺便说一句,您的示例代码没有理由进行连接,因为条件或答案中没有使用任何连接范围变量,并且无论如何您都会连接每个变量,因此将它们排除在外将是最快的解决方案。
一些想法:
首先,您正在搜索字符串。如果要搜索的内容很多,请考虑维护全文索引以加快搜索速度。
其次,将where
条款放在join
条款之前。筛选出数据的内容应在 LINQ 语句中尽可能高的位置。它目前正在为每一行加入一堆数据,即使如果 where
子句为 false,也不会使用它。