【问题标题】:PHP/MySQL - Hashing To BIGINT To Ensure No DuplicatesPHP/MySQL - 散列到 BIGINT 以确保没有重复
【发布时间】:2015-07-04 09:21:28
【问题描述】:

我目前正在从网页上抓取虚拟货币交易数据。交易包括时间/日期、描述、价格和新余额。

结果是分页的。我一次可以拿20个。我的目标是在单独的数据库中准确记录所有条目。发生了大量事务,并且事务可以随时发生,包括在获取不同页面之间。

时间/日期以分钟计,因此可以在同一分钟内发生多个事务。描述也可以相同(例如,同一物品可以以相同数量多次出售给同一个人)。价格和余额也可能重叠。

我正在存储一个时间戳、价格、余额和从多个字段中的描述中解析的数据。我需要能够快速判断一个条目是否已经在数据库中。我能得到的最大效果是确保每个条目都有唯一的时间/数据、描述、价格和余额。复合键的问题是我不想将完整的描述存储在数据库中。 (这会使数据库大小翻倍。)

我想出的解决方案是基于这些字段创建一个 BIGINT 哈希,该哈希将用作数据库中的唯一字段。我发现碰撞的概率 (based on the birthday attack formula) 对于多达 6100 万个条目来说将小于 1%,这是一个令人满意的概率,因为我计划跟踪的条目数量在 40k 左右- 2m。

我的问题是,根据我的应用程序和目标,您会推荐哪种散列算法,以及如何在不丢失算法任何属性的情况下将其中的值转换为 BIGINT 大小?最重要的是避免冲突,因为每一个都会影响数据的完整性。除非您有更好的主意,否则我的计划是将数据连接成一个字符串(字段之间有分隔符),然后将其输入函数。非常感谢短代码sn-ps!

【问题讨论】:

  • 您写道“在 MySQL INSERT 查询期间与所有这些字段进行比较会很慢”。你有什么证据?还是你猜这是真的?如果你把它们变成一个复合唯一键并执行 INSERT IGNORE,你的问题应该会很好地解决。
  • 跨四列的复合索引将使您能够比散列更快地执行查找......并且可以准确地提供您想要的东西。但是,交易本身必须具有某种唯一标识符——抓取网页真的是获得它们的唯一方法吗?许多虚拟货币都公开了一个您可以直接访问的区块链......
  • 我不太了解复合键如何分析性能,但是我的直觉告诉我,与一个 BIGINT 进行比较必须比与多个字符串字段进行比较更快。我也不希望将整个描述存储在数据库中,这对于复合键是必需的。这个描述是一个句子,在关键数据之间有很多无用的词,并且可能会使数据库的大小增加一倍。
  • 这不仅仅是“与一个 BIGINT 的比较”……您必须首先计算哈希!这与直接为仅比BIGINT 大几个字节的组合键遍历索引树?我几乎肯定会赌后者。
  • 对。我当时认为散列对于插入来说是一次性的,并且忘记了无论如何每次比较都必须再次进行散列。所以现在唯一的缺点是存储描述。上次数据变得如此之大,我无法轻松导出它,尽管我认为这两种情况都会发生。出于任何其他原因,我不需要描述。

标签: php mysql algorithm hash transactions


【解决方案1】:

因为我不关心安全性,所以我使用了 SHA1。这会生成一个 20 字节的十六进制字符串。 BIGINT 大小为 8 个字节。因此,我们需要使用 substr 将其截断为 16 个字符(因为每个字符在 hex 中是半个字节),并使用 base_convert 转换为 base 10 用于数据库存储。

function hashToBigInt ($string) {
  return base_convert(substr(sha1($string), 0, 16), 16, 10);
}

感谢大家的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多