【问题标题】:Should I use MySQL indexes of MD5 32 chars or a ~8 chars index that contains special chars?我应该使用 MD5 32 字符的 MySQL 索引还是包含特殊字符的 ~8 字符索引?
【发布时间】:2021-02-09 05:10:47
【问题描述】:

我有一个包含大约 1 亿个 url 的数据库,出于分片目的(以及识别唯一 url),我将每个条目索引设为完整 url 的 md5 哈希。

MD5 仅由 16 个可能的字符组成:0123456789abcdef,总长度为 32 个字符。

如果我使用较短的索引(如 8 个总字符),我应该期待什么性能优势(如果有的话)?例如使用包含大写、小写和特殊字符的散列函数(可能是自定义的)。

或者它会因为索引使用更多可能的字符而导致性能下降? (即使索引长度较短~8)。

【问题讨论】:

  • 这是最好的问题之一理论。 MySQL 在实际负载下的行为方式完全无法预测。
  • 另外值得注意的是,MD5 非常脆弱,如果你有那么多条目,你实际上可能会发生冲突。值得检查。 SHA2-256 是一个更安全的选择,但这可能会破坏这里的目的。

标签: mysql performance indexing database-performance


【解决方案1】:

简答:我推荐使用 INDEX(hash, id) 的 Plan C,确保它是一个二级索引。

长答案和一些讨论:

A 计划:只需使用 url。效率最低。

方案 B:使用 32 字节的 CHAR(32) CHARSET ascii 表示十六进制 MD5。更好但不是最好。

Plan C:UNHEX(..) 并放入BINARY(16)(16 字节)。更好。

计划 D(如您所建议):仅使用这 16 个字节中的一部分。 有一些重复。这可能会破坏使用较短摘要的速度优势。

Plan E:位模式加查找。甚至可能更快。 (但首先,让我解释一些问题。)

你有多少内存?你有多少磁盘?

大概您的磁盘上有 10-20GB 所需的空间。但是您的 RAM 中是否还有更多?如果您不这样做,那么我们需要讨论缩小查找,否则所有计划将退化为必须以某种频率访问磁盘。

桌子长什么样子?

  • 哈希 + 完整 URL + 杂项;使用idhash 作为PRIMARY KEY
  • INDEX(hash, id) -- 你会在这里花费大部分精力,这比完整的表要小得多。对于 100M 行,此二级索引使用 Plan C 大约需要 5GB。除非所有 5GB 都可以在 RAM 中存活,否则您会四处乱跳,因此无法缓存。
  • Plan E 尝试通过首先查看可以将查找压缩到大约 0.2GB 的位字符串来缩小索引。 存在需要仔细检查的重复项(例如,使用计划 C),但可能只有 5-10% 的时间。如果您愿意,我们可以进一步讨论。

如需进一步讨论,请提供 RAM 大小,以及完整的CREATE TABLE 和建议的“检查 dup”SELECT

尺寸

  • 1 位只能表示 2 个不同的值
  • 1 个十六进制数字只能代表 4 个不同的值
  • 1 个字节(8 位)可以表示 256 (2^8) 个不同的值
  • 100M ~= 2^23(用于比较)
  • INT是4个字节:2^32,足够容纳1..100M
  • BIGINT 为 8 个字节:2^64,比几乎所有 id 使用所需的都要大
  • 8 字节,假设您使用所有可能的组合:256^8 = 2^64 = a-very-large-number
  • MD5 有 128 位(表示为 32 个十六进制数字或 16 个二进制字节):2^128 -- 一个更大的数字

判断重复的可能性:

  • 给定 2^M -- 例如,对于 MD5,M=128; BIGINT 为 64
  • 计算 N=(M+1)/3 -- MD5: 43;大整数:~22
  • 说:在 2^N 行中找到 dup 的几率是 1/2^N。

也就是说,

  • 使用 md5 重复的几率:如果您有 2^43(9 万亿)个值,则只有 9 万亿分之一。
  • 8 字节哈希的重复概率:如果有 600 万行,重复的概率约为 600 万分之一。

【讨论】:

    猜你喜欢
    • 2017-09-06
    • 2011-10-24
    • 1970-01-01
    • 2011-03-31
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 2017-06-17
    相关资源
    最近更新 更多