【问题标题】:Is it faster to search for a large string in a DB by its hashcode?通过哈希码在数据库中搜索大字符串是否更快?
【发布时间】:2009-03-18 12:31:48
【问题描述】:

如果我需要从数据库中检索一个大字符串,使用字符串本身搜索它是否会更快,或者我会通过对字符串进行散列并将散列存储在数据库中然后基于它进行搜索来获得?

如果是,我应该使用什么哈希算法(安全不是问题,我正在寻找性能)

如果重要的话:我正在使用 C# 和 MSSQL2005

【问题讨论】:

  • 不确定它是否与 .net 或 c# 相关,但...

标签: database performance hash


【解决方案1】:

一般来说:可能不会,假设列已编入索引。数据库服务器旨在快速有效地进行此类查找。一些数据库(例如 Oracle)提供了基于散列构建索引的选项。

但是,最终这只能通过使用代表性(您的需求)数据和使用模式进行性能测试来解决。

【讨论】:

    【解决方案2】:

    如果这提供了巨大的改进,我会感到惊讶,我建议不要使用您自己的性能优化来进行数据库搜索。

    如果您使用数据库索引,则 DBA 可以使用久经考验且值得信赖的方法来调整性能。对您自己的索引优化进行硬编码将防止这种情况发生,并且可能会阻止您在未来版本的数据库中获得任何索引性能改进。

    【讨论】:

      【解决方案3】:

      虽然我从未这样做过,但听起来这在原则上是可行的。您可能会得到误报,但这可能非常小。

      我会使用 MD5 之类的快速算法,因为您不想花费更长的时间来散列字符串,而不是仅仅搜索它。

      我要说的最后一点是,只有尝试并衡量性能,您才会知道它是否更好。

      【讨论】:

        【解决方案4】:

        你是在进行平等匹配,还是包含匹配?对于 平等 匹配,您应该让 db 处理这个(但添加一个非聚集索引)并通过 WHERE table.Foo = @foo 进行测试。对于遏制匹配,您或许应该查看full text index

        【讨论】:

          【解决方案5】:

          首先 - 测量它。这是唯一可以确定的方法。
          第二 - 如果您对字符串搜索的速度没有问题,请保持简单,不要使用哈希。

          但是,对于您的实际问题(并且只是因为这是一个有趣的想法)。这取决于字符串的相似程度。请记住,数据库引擎不需要比较字符串中的所有字符,只需要找出差异即可。如果您正在查看 1000 万个都以相同的 300 个字符开头的字符串,那么哈希几乎肯定会更快。但是,如果您正在寻找唯一以 x 开头的字符串,那么字符串比较可能会更快。我认为尽管 SQL 仍然必须从磁盘获取整个字符串,即使它只使用第一个字节(或多字节字符的前几个字节),所以总字符串长度仍然会产生影响。

          如果您正在尝试哈希比较,那么您应该使哈希成为索引计算列。如果每次运行查询时都计算所有字符串的哈希值,它不会更快!

          您也可以考虑使用 SQL 的 CRC 函数。它会产生一个 int,它的计算速度更快,计算速度也更快。但是您必须通过实际测试字符串值来仔细检查此查询的结果,因为 CRC 函数不是为这种用法而设计的,而且更可能返回重复值。您将需要在一个查询中进行 CRC 或哈希检查,然后有一个比较字符串的外部查询。您还需要查看生成的 QEP,以确保优化器按照您想要的顺序处理查询。它可能决定先进行字符串比较,然后再进行 CRC 或哈希检查。

          正如其他人所指出的,这只有在进行完全匹配时才有用。如果您尝试进行任何类型的范围或部分匹配,哈希将无济于事。

          【讨论】:

          • 嗯,哈希值是一个数字,因此将单个数字与另一个数字进行比较总是比比较字符串要快。即使在您的唯一以 x 开头的字符串的示例中,它仍然需要比较 Ascii 值。
          • 哈希值不是一个数字,它是一个 varbinary。 x 的 ascii 值不是数字吗?
          【解决方案6】:

          如果你的字符串很短(一般少于 100 个字符),字符串会更快。

          如果字符串很大,HASH 搜索可能会更快。

          HashBytes(MD4) 似乎是DML 上最快的。

          【讨论】:

            【解决方案7】:

            如果您使用固定长度的字段和索引,它可能会更快...

            【讨论】:

              【解决方案8】:

              提示:如果要将哈希存储在数据库中,MD5 哈希始终为 16 个字节,因此可以保存在 uniqueidentifier 列中(和 .NET 中的 System.Guid)

              与以不同方式保存哈希相比,这可能会提供一些性能提升(我使用此方法来检查二进制/ntext 字段更改,但不检查字符串/nvarchars)。

              【讨论】:

                【解决方案9】:

                “理想”的答案肯定是肯定的。 与索引列匹配的字符串总是比匹配存储在索引列中的哈希值慢。这就是哈希值的设计目的,因为它们采用大型数据集(例如 3000 个比较点,每个字符一个)并将其合并成一个较小的数据集(例如,16 个比较点,每个字节一个)。

                所以,最优化的字符串比较工具会比优化的哈希值比较慢。

                但是,如前所述,实现您自己的优化散列函数是危险的,并且可能不会顺利进行。 (我已经尝试过但失败得很惨)哈希冲突并不是一个特别的问题,因为那样你将不得不依赖字符串匹配算法,这意味着它(在最坏的情况下)与你的字符串比较方法一样快。

                但是,这一切都假设您的散列以最佳方式完成(可能不会)并且您的散列组件中不会有任何错误(会有)并且性能增加将是值得的努力(可能不是)。字符串比较算法,尤其是在索引列中已经相当快了,而且散列工作(程序员时间)可能比您可能获得的收益要高得多。

                如果您想了解性能,只需测量即可。

                【讨论】:

                  【解决方案10】:

                  我很困惑,可能误解了你的问题。

                  如果您已经有了字符串(因此您可以计算哈希),为什么需要检索它?

                  您是否使用大字符串作为某事的键?

                  【讨论】:

                  • 好点。我想我没有说清楚。我有字符串,但我想检索存储在数据库中的其他相关信息。
                  • 那为什么不考虑使用字符串以外的东西来查找那些相关的东西呢?但无论如何,我同意最佳答案(atm),你应该测试和测量。
                  猜你喜欢
                  • 2020-09-03
                  • 2011-09-06
                  • 2021-01-22
                  • 2018-09-06
                  • 2021-08-12
                  • 2019-08-08
                  • 2011-09-02
                  • 2011-01-15
                  • 2014-06-01
                  相关资源
                  最近更新 更多