【问题标题】:Speed up looping through a dictionary in VB.Net 2008在 VB.Net 2008 中加快遍历字典的速度
【发布时间】:2011-05-17 21:21:34
【问题描述】:

我有一个流程可以导入产品注册的每日文件,并将它们添加到我们的数据库中。最初,此过程会针对每条记录多次查询数据库以确定如何处理数据。

为了加快此过程并防止尝试使用使用相同数据库的报告站点的人可能出现的任何超时问题,我更改了代码以将一些表下拉到字典中,并且然后遍历它们以查看该客户/地址/经销商是否存在,如果存在则从字典的键中提取 Id,或者将其插入表中,如果不存在则将其插入字典中。

但是,我目前发现它的运行速度要慢,因为每次注册都要多次查询数据库。我能想到的一个可能原因是我的字典很大(一个有 800 万个条目,另一个有 1100 万个)。

这是我正在做的一个例子:

    For Each kvp As KeyValuePair(Of Int64, String) In dCust
            If kvp.Value = firstName & "|" & lastName & "|" & companyName & "|" & addrId & "|" & typeID & "|" & phone & "|" & email Then
                custId = kvp.Key
                Exit For
            End If
    Next

这本词典有大约 1100 万条记录。

我的一个同事的一个想法是在循环之前运行Dictionary.ContainsValue() 以查看它是否存在。如果它没有完全跳过循环。如果它比循环本身运行得更快,我只想尝试这个,如果它们花费相同的时间,我看不到基本上运行循环两次的意义。

所以我的问题是:

  • 我最关心这个 有效的方法?
  • 会更快吗 之前运行Dictionary.ContainsValue() 尝试循环,或者将 系统将它们解释为相同 事情,从而使我的时间翻倍?
  • 我还有什么需要寻找的吗?

【问题讨论】:

  • 您正在计算firstName & "|" & lastName & "|" & companyName & "|" & addrId & "|" & typeID & "|" & phone & "|" & email 1100 万次?尝试在循环之前只计算一次。
  • @Gabe,你比我快 50 秒!
  • Dictionary.Values 总是唯一的吗?如果是这样,反转您的键值对(如几个回复所述)是一个好主意。

标签: .net vb.net dictionary


【解决方案1】:

一个明显的小优化是在循环外执行firstNamelastName等的串联一次。目前,您正在对循环的每次迭代进行连接,这显然比它可能的要慢。

不,使用 ContainsValue 不会更快 - 仍然需要进行线性搜索。

明显的 优化将是反转字典 - 创建一个 Dictionary(Of String, Int64),它基本上具有每个字符串值的 ID。目前,您没有使用字典的自然优势 - 您实际上是在将其视为键/值对列表。

您是否也以正常的方式使用字典(通过键查找)?

【讨论】:

    【解决方案2】:

    看起来您使用字典的方式与应该使用的方式相反 - 还是我遗漏了什么?

    通过迭代字典中的键、值对,您将抵消字典(哈希表)提供的好处 - 快速查找给定键值的好处。

    您应该使用 (String, Int64) 的字典,将 firatname、lastname、... 映射到 custId。与您当前所做的相比,查找此内容会非常快。

    【讨论】:

      【解决方案3】:

      为了加快速度,您可以做的一件事是预先连接该搜索字符串:

      Dim SearchValue as String = firstName & "|" & lastName & "|" & companyName & "|" & addrId & "|" & typeID & "|" & phone & "|" & email
      For Each kvp As KeyValuePair(Of Int64, String) In dCust
              If kvp.Value = SearchValue Then
                  custId = kvp.Key
                  Exit For
              End If
      Next
      

      【讨论】:

        【解决方案4】:

        使用字典的目的是快速查找 KEY 而不是值。要么只使用普通的数组列表,要么更改代码,以便进行键查找而不是值查找。

        【讨论】:

          【解决方案5】:

          我认为关于字典的答案很好,但我认为更广泛的答案是在数据库层处理这些东西,而不是下载数百万条记录来迭代使用 C# 中的字典。为什么不使用table valued parameter(我假设您使用的是SQL Server 2008)来传递您想要比较的数据并查看它是否存在?您可以将它传递给存储过程或在 SQL 端进行比较的东西。你甚至可以这样做:

          INSERT ProductRegistrations
          SELECT * FROM @tvpProductsToAdd pa WHERE
          pa.firstName + pa.lastName + pa.companyName NOT IN
          (SELECT firstName + lastName + companyName FROM ProductRegistrations)
          

          @tvpProductsToAdd 是您在新产品中传递的表值参数。鉴于您似乎没有可以比较的键,您可能希望在这些字段上创建某种索引以加快比较速度。

          【讨论】:

            猜你喜欢
            • 2014-09-16
            • 2015-05-19
            • 2020-02-02
            • 1970-01-01
            • 1970-01-01
            • 2012-12-06
            • 2013-07-14
            • 2019-10-21
            相关资源
            最近更新 更多