【问题标题】:Linq To SQL Performance on IndexOfIndexOf 上的 Linq To SQL 性能
【发布时间】:2019-01-23 11:34:14
【问题描述】:

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

我们已经按照this link 中的解决方案尝试了 StartsWith,但它只适用于 EF。

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

问题是在大桌子上速度很慢。我们的姓氏表有 100 万条记录,查找表大约有 50 000 条。

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

(比较的所有字段部分都已打开索引)

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

【问题讨论】:

  • 您确定这与 EF 或 Linq2SQL 有关吗?在这样的数据库中进行大量文本查找可能会非常缓慢。您能否编写一个足够快的 SQL 查询?
  • 我还没有尝试编写自己的 SQL,因为这确实是最后的手段。由于维护等优点,首选Linq。
  • 你真的应该看看生成的 SQL 代码。但除此之外,StartsWithIndexOf >= 0 并不相同,并且会产生截然不同的性能影响。
  • 我的意思不是嵌入 SQL,而是说您不能编写能够快速完成此操作的 SQL 查询。文本查找速度非常慢。
  • 你的前缀总是一样长吗? > 然后将相应的预截断值存储在 Personnel 表的新索引列中,并与相等性进行比较。

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


【解决方案1】:

问题是在大表上速度很慢

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

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

你能做的是:

  • 在使用较低事务保证 (Readcommitted) 的单独连接上执行这些操作,这样您就不会在表上留下锁。标准连接是可序列化的,完全不适合查找表。
    • 您可能希望隐藏该表并使用一个索引,该索引使用 readcommmitted 转发该表。
  • 或者将它们加载到内存中一次,然后在内存中并行运行,这取决于这是否是服务器代码。

最后,查看 IN 字符串是一项极其繁重的工作,您可以做的事情很少,而且 SQL 通常没有为此进行优化。这既不是 EF 也不是 Linq2SQL 问题——就像您的驾驶执照不能确定您的汽车不是飞机一样。 SQL 通常不能很好地处理这种类型的查询。

【讨论】:

  • 谢谢。它并没有让我对快速解决方案充满希望,但至少我们的回答证实了我最糟糕的怀疑,并将为我指明正确的方向。发送!
  • 是的,这只是一个简单的示例。否则我可能不得不解释很多其他的事情。类似于数据仓库,其中数据来自不同的系统,需要进行比较和过滤。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多