首页 > 解决方案 > 使用“LIKE”解决 Linq 上的性能问题

问题描述

我有一个包含 25,000 条记录的识别表,以及一个必须使用 LIKE 匹配识别的传入字符串表,通常每批在 200 到 4000 之间。这曾经在 sql server 中,但我试图通过在内存中完成这一切来让它更快,但是 linq 慢得多,当传入表有 200 行时,在 sql 中需要 5 秒而不是 250 毫秒。

识别表声明如下:

Private mRecognition377LK As New SortedDictionary(Of String, RecognitionItem)(StringComparer.CurrentCultureIgnoreCase)

实际的类似比较在这里:

r = mRecognition377LK.FirstOrDefault(Function(v As KeyValuePair(Of String, RecognitionItem)) sTitle Like v.Key).Value

因此,这对每条传入记录都执行,我认为使用 v.key 将使 linq 引擎不扫描以不同字符开头的记录,但似乎不是。

我可以重新发明轮子并创建一个集合类,将识别表拆分为其组成部分

例如,如果传入的字符串是 abcdef 并且我们有“abc*”的识别记录,那么我可以存储按识别项的长度分组的集合,直到第一个星 (3),然后在其中存储具有该长度的识别项的集合,将文本键入到第一个星 (abc)

所以 abc* 的字符串长度为 3,所以:

r = Itemz(3).Recog("abc")

我认为这会工作并且表现良好,但它有很多问题,而且我确信集合类和 linq 的设计方式可以使这样一个简单的事情可以在没有这种性能拖累的情况下快速执行。

所以我的问题是有没有一种方法可以在不采用我提出的解决方案的情况下快速进行?

答复草案

因此,在编写了多次 TRIE 和二进制搜索迭代后,我意识到所有这些都是过度处理,这是因为......

两个列表都已排序

...这意味着我们只需要一个循环来处理两个列表并加入它们,即我们在 C#/VB 中执行 Sql Server 在执行 MERGE 连接时所做的事情。所以现在我正在追求这个作为解决方案,并将在此处酌情更新。

最后更新

解决方案现已完成,您确实可以加入任意数量的列表,只要它们都按您要加入的属性按升序或降序排序,并且您可以在单个循环中执行此操作(因为它们已排序)。我的代码大约有 1000 行并且非常具体,所以我不打算发布代码解决方案,但是对于将来遇到此类问题的任何人,似乎 linq 中没有任何内容可以帮助进行合并连接,即不基于相等性(我们有 LIKE 匹配),因此当对传入数据进行排序时,可以在单个循环中编写自己的合并连接。

该算法的基础是遍历作为“可维护表”的表,并将指针推进到彼此的列表中,直到文本比较大于或等于。当它相等时,您不会再次推进此列表,直到它与 maintable 列表不匹配,因为右侧的一个项目可以连接左侧的许多项目。这可以对多个数组重复。

很高兴看到一个库,您可以在其中传递 lambda 函数来对多个排序数组执行合并连接。以后会考虑写一篇。

该解决方案在 0.007 秒内运行,将 200 条记录加入到 70,000 条记录识别列表中。linq 有效地执行内部循环,需要 5 秒。将 4000 条记录连接到同一个 70000 条记录识别列表时,性能仅略微下降到 0.01s 左右,显示了合并连接逻辑的巨大有效性。Sql server 花了大约 250 毫秒来执行连接。

标签: vb.netlinq

解决方案


推荐阅读