【问题标题】:What if 2^32 is just not enough?如果 2^32 还不够怎么办?
【发布时间】:2010-10-16 17:19:40
【问题描述】:

如果表中有如此多的条目,那么 2^32 不足以满足给定时间段(日、周、月……)内的 auto_increment ID 怎么办?
如果 MySQL 提供的最大数据类型不够用怎么办?

我想知道我应该如何解决这样一种情况:我的表中添加了这么多需要唯一 ID 的条目,但我在一段时间内填写了我的数据类型?

我怎样才能在 MySQL(或任何其他系统)内实现无限数量的唯一 ID 或至少成倍增加?

理想情况下我会期待类似的东西

> SELECT * FROM table;

+---+------+
| a |  b   |
+---+------+
| 1 |  1   |
| 1 |  2   |
| 1 |  3   |
|...| .... |
|...| .... |
| 1 | 2^32 |
| 2 |  1   |
| 2 |  2   |
+---+------+

这会成倍增加条目的数量。

您如何应对这种情况?
请记住 - 要求任何条目都必须具有唯一 ID。

【问题讨论】:

  • 有兴趣知道什么样的数据需要如此高的 ID

标签: sql mysql database primary-key large-data-volumes


【解决方案1】:

只需使用 128 位密钥。不需要无限数量的键,因为您很快就会允许比宇宙中的原子数量更多的行。 (大约 256 位)。

【讨论】:

    【解决方案2】:

    不要使用自动递增的主键 - 使用 GUID 或类似的 - 来自维基百科文章:

    虽然每个生成的 GUID 不是 保证唯一,总 唯一键的数量(2^128 或 3.4×10^38) 如此之大,以至于相同数字出现的概率 生成两次是无穷小的 小的。例如,考虑 可观测宇宙,其中包含 大约5×1022颗星;每颗星星都可以 然后有 6.8×1015 普遍唯一 GUID。

    【讨论】:

    • 不认为 MySQL 对 GUID 有原生支持吗?
    • 然后得到一个可以处理你需要的RDMS。
    • 查找“生日悖论”。实际上,在您生成 2^64 个 GUID 时,您将有大约 50% 的机会两次获得相同的 GUID。所以它比使用 64 位自增类型没有优势。
    • 取决于您用于生成 GUID 的算法。大多数都涉及某种时间计数器。
    【解决方案3】:

    我不确定如何在 MySQL 中自动生成它们,然后它们不一定是顺序的,但我很确定您可以使用 GUID 而不必担心它们会被填满。

    【讨论】:

      【解决方案4】:

      您可以使用 BIGINT 作为主键。默认为 64 位数字。

      编辑#2:显然我之前所说的关于改变 BIGINT 字节长度的内容是不正确的。 BIGINT 固定为 8 字节限制。

      【讨论】:

      • dev.mysql.com/doc/refman/5.1/en/numeric-types.html 暗示 BIGINT 固定为 8 个字节?
      • 实际上 Rowland 所说的是正确的 - BIGINT 始终是 64 位的。可与数值数据类型关联的数字仅定义显示宽度,对存储容量没有影响。
      • 我很困惑 8 字节和 64 位是一回事吗?那么为什么要编辑呢?
      • 通常情况下,8字节和64位是等价的,这是一个典型的例子。我之所以编辑是因为我还建议 BIGINT(n) 改变字节长度,这是不正确的。
      【解决方案5】:

      我会从 2^64 移动到 BIGINT 开始。 GUID 是另一种选择,但您需要自己以“某种形式”存储它们

      【讨论】:

        【解决方案6】:

        您还可以将 chars/varchars 用于您的键列,并将 GUID 用于您的键。不过,与整数主键相比,我不知道这是否会导致性能损失。

        【讨论】:

          【解决方案7】:

          当您将另一列添加到您的键时,您实际上需要执行的索引扫描次数加倍(尽管第二列的索引要小得多)。

          如前所述,VAST 数据集的最佳选择是 GUID(如果您的 RDBMS 本身支持它)或 varchar(16)。

          使用 varchar / varbinary 的好处在于,如果需要,您可以在将来自动扩展列。不好的部分是 varchar / varbinary 与整数相比是性能较差的键。

          【讨论】:

            【解决方案8】:

            如果您有太多数据而遇到此问题,那么选择主键可能是您最不关心的问题。

            如果您使用 InnoDB 引擎,选择您将经常搜索的主键(尤其是在搜索返回许多行的情况下)可能有助于提高性能,因为它会聚集主键,这使得范围扫描更好。

            【讨论】:

              【解决方案9】:

              您不认为BIGINT UNSIGNED 就足够了吗?这是 0 - 18.446.744.073.709.551.615 的范围,或一年每天 50.539.024.859.478.223 条目(365 天/年),每小时 2.105.792.702.478.259 条目,每分钟 35.096.545.041.304 条目或每秒 584.942.417.355。

              With assumed 600 writes per second (without any reads) 你可以以全速写入条目 974.904.028 年。应该够了。

              【讨论】:

                【解决方案10】:

                如果 BIGINT 对您来说不够用,请在您的表中使用它,当条目数量达到 BIGINT 边界时,创建另一个表并从 0 重新开始。现在您将有 2 个表来存储相同类型的数据.

                【讨论】:

                  猜你喜欢
                  • 2011-11-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-06-22
                  相关资源
                  最近更新 更多