我有一个包含唯一字符串值列的表。字符串值的最大长度为 255 个字符。我想生成一个以字符串值作为输入的唯一 id。换句话说,我正在寻找一个字符串的紧凑表示。生成的唯一 ID 可以是字母数字。一个有用的功能是能够从唯一 id 重新生成字符串值。
是否有一个有效的函数来生成这样一个唯一的 id。一些方法可能是使用校验和或哈希函数。我想知道是否有标准的方法来做到这一点。
我正在使用 MySql 数据库和 java。
谢谢!
--edit:我正在寻找更紧凑的表示,而不仅仅是使用字符串本身。
我有一个包含唯一字符串值列的表。字符串值的最大长度为 255 个字符。我想生成一个以字符串值作为输入的唯一 id。换句话说,我正在寻找一个字符串的紧凑表示。生成的唯一 ID 可以是字母数字。一个有用的功能是能够从唯一 id 重新生成字符串值。
是否有一个有效的函数来生成这样一个唯一的 id。一些方法可能是使用校验和或哈希函数。我想知道是否有标准的方法来做到这一点。
我正在使用 MySql 数据库和 java。
谢谢!
--edit:我正在寻找更紧凑的表示,而不仅仅是使用字符串本身。
“独特”有多独特?使用任何好的散列函数(MD5 适合大多数用途,并且可以通过 java.security.MessageDigest.getInstance("MD5") 轻松实现)可以让您获得一个非常可能是唯一的 128 位数字。使用哈希使您的 ID 更小,碰撞的可能性更高。
在 DB 中使用 auto_increment 字段,如果它适合您的设计,可能更容易实现,将真正保证唯一性,并且将使用比 MD5 的 16 字节更小的 ID。然后,您还可以满足通过键查找字符串的要求,而这对于哈希是无法做到的。
这与压缩有关。最简单的方法是对每个字符进行位打包并将每个字符降至最低位数。
AZ 是 26 个字符,小于 32(5 位)
添加 az 并且它是 6 位(大约 12 位模式剩余的某处代表其他字符)。
假设这对你来说已经足够了。所以你有 6x255 位,即 1530 位来存储你的字符串。(191 字节)
只使用大写字母会减少一点(到 159 字节)
您可以对其进行更多优化,但随后您必须进入一种压缩算法,该算法需要字符串中的特定语言或模式并优化这些模式。
除非您可以进一步指定字符串的内容,否则您不会得到您想要的。对不起。(如果您可以详细了解字符串的内容,请这样做。我们中的一个人可能会看到允许更好“压缩”的模式)
缺乏做你想做的事的能力就是哈希表如此酷的原因。他们得到一个“最唯一”的数字,然后有第二级的分辨率来测试两个字符串散列到相同数字的情况。
如果您的数据库要求列包含唯一值,那么为什么不使用字符串本身呢?其他任何东西都只是编码/解码它的另一个步骤。
255 长的字符串比 64(或其他)长的数字有更多的可能性。是不可能的。添加一个 auto_increment 字段。
由于您使用的是 MySQL,请查看 CRC32
public String getUniqueId(String uniqueString) {
return uniqueString;
}
除非 ID 对它有任何其他限制,而不是“唯一”。
如果您有有限数量的频繁出现的字符串,则可以选择创建一个具有数字(自动递增)ID 的引用表,并在主表中对该引用表进行 FK。
如果没有,您可以通过 GZIP 或任何其他压缩算法运行您的字符串,如果您需要检索原始文件。
如果您不需要检索原始文件,那么您正在寻找诸如 MD5 之类的散列函数。
选择正确的密钥并不容易。
你需要考虑:
复制:是否需要在不同服务器之间共享密钥?如果是这样,您很可能需要某种唯一的哈希或 guid。
表的大小/插入的数量:您应该考虑大多数 rdbms 按其(集群)主键的顺序将数据物理存储在硬盘上。现在想象一下,如果您在具有合理大小的表上插入以“a”开头的哈希值,会发生什么。是的,有索引填充,但最终它的完整和单行插入可能会导致硬盘驱动器上的几个 GB 移动。
需要复制并且有大表?两者都用。使用主聚集自动增量(长)整数键并在哈希列上定义唯一索引。