代码之家  ›  专栏  ›  技术社区  ›  birdus

针对强类型数据集的慢速LINQ查询

  •  0
  • birdus  · 技术社区  · 9 年前

    我有一个数据库,其中大约有5000行。还有许多多对多关系。作为“高级搜索”查询的一部分,我需要跨表进行自由文本搜索。

    我创建了一个强类型数据集,并在应用程序启动时从SQL Server导入所有数据。对数据集执行LINQ查询时,查询执行速度非常慢(约15秒)。我认为对内存数据集执行查询要比SQL Server快得多,但事实似乎并非如此。我甚至需要在where子句中添加更多连接和“搜索”,所以事情只会变得更糟。

    在我搜索的字段中,最长的是摘要,数据库中最长的字段不到2000字节,所以我们并不是说要搜索很多数据。我在这里选错了树了吗,或者有没有办法提高这个查询的性能?

    代码如下:

    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
          };
    
    2 回复  |  直到 9 年前
        1
  •  1
  •   NetMage    9 年前

    假设您仍然加载到 DataSet

    预加入数据以用作搜索索引:

    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
              };
    

    顺便说一句,您的示例代码没有显示进行连接的理由,因为在条件或答案中没有使用任何连接范围变量,而且您仍然需要连接每一个变量,因此只需将它们排除在外就是最快的解决方案。

        2
  •  1
  •   Cory Nelson    9 年前

    一些想法:

    首先,您正在搜索字符串。如果要搜索的内容很多,请考虑维护全文索引以加快搜索速度。

    第二,把 where join 条款。在LINQ语句中,过滤数据的内容应该尽可能高。目前,它正在为每一行加入一组数据,即使在以下情况下也不会使用它: 哪里 条款是错误的。