Linq在IndexOf上的SQL性能

时间:2019-01-23 11:34:15

标签: c# performance linq linq-to-sql

我们正在使用LINQ来过滤SQL表,以查找列中的数据以在另一个表中找到的任何子字符串(带有长前缀列表的查找表)开头的记录。

我们已根据this link中的解决方案尝试了StartsWith,但它仅在EF中有效。

但是this post确实为LinqToSQL提供了正确的解决方案。

问题是在大型表上它的速度非常慢。我们的姓氏表有100万条记录,查找表大约有5万条。

这是我们当前代码的示例。我们如何提高性能?

(比较的所有字段都已经有索引)

var lookupList = LookupTable.Select(p => p.Prefix);
var q = from p in dc.Personnel
        where lookupList.Any(x => p.Surname.ToUpper().IndexOf(x) >= 0)
        select new 
        {
            Surname = p.Surname
        };

1 个答案:

答案 0 :(得分:1)

  

问题在于在大型表上它非常慢

问题是设计者不了解SQL基础知识。

IndexOf-或任何不以字符串开头开头的内容-会破坏可拼写性。期。这意味着将不使用任何索引。这意味着基本上您要进行表扫描,并且在每个表上都必须经过char并将它们进行比较,直到...好。而且ToUpper实际上没有做任何事情-字段比较是在SQL级别上由排序索引确定的,除非进行“上下限考虑”,否则您手上只有一个非操作。

您可以做的是:

  • 在单独的连接上执行,这些连接使用较低的事务保证(已提交读),因此您不会在表上留下锁。标准连接是可序列化的,完全不适合查找表。
    • 您可能想要隐藏表,并使用通过readcommmitted为此表转发索引的索引。
  • 或者将它们加载到内存中一次然后在内存中并行运行,取决于这是否是服务器代码。

最后,查找IN字符串非常费时,并且您几乎无能为力,并且SQL通常没有为此优化。这既不是EF也不是Linq2SQL问题-差不多是因为您的驾驶执照并不能确定您的汽车不是飞机。 SQL通常不会适当地处理这种类型的查询。