sql字符串文字十六进制键到二进制并返回

hfwmuf9z  于 2021-06-25  发布在  Mysql
关注(0)|答案(1)|浏览(385)

经过广泛的寻找,我求助于堆积如山的智慧来帮助我。问题:我有一个数据库表,它应该有效地存储格式的值 (UserKey, data0, data1, ..) 在哪里 UserKey 将作为主键处理,但至少作为索引处理。userkey本身(外部定义的)是一个由32个字符组成的字符串,表示一个校验和,它恰好是(一个非常大的)十六进制数,即 UserKey = "0000000034f6e0000000034f6e" .
现在我当然可以将这个userkey存储在char(32)字段中,但我觉得这非常低效,因为我存储了一系列原则上任意的字符,即为每个字符预留空间,以便存储比存储十六进制字符(0..9,a-f)所需的4位更多的信息。
所以我的想法是把这个字符串文字转换成它真正代表的十六进制数,然后存储起来。但是这个数字(32*4位=16字节)太大了,无法存储/处理,因为sql只处理8字节的大整数。
我的第二个想法是把它转换成二进制(16)表示,它应该是紧凑和高效的内存。但是,我不知道如何在这两种格式之间高效地转换,因为sql在内部也只处理最多8字节的数字。
也许有一种方法可以将这个字符串逐块转换成二进制,并以某种方式将二进制缝合在一起,方法如下:

UserKey == concat( stringblock1, stringblock2, ..)
 UserKey_binary = concat( toBinary( stringblock1 ), toBinary( stringblock2 ), ..)

所以我的问题是:在sql中有没有这样的机制可以为我解决这个问题?定制解决方案是什么样子的(我发现很难相信我会是第一个遇到这种问题的人,因为在许多应用程序中使用长得离谱的哈希键已经变得相当现代了。)
此外,还有 Userkey_binary 而不是充当表的关系键,因此我希望通过这种更紧凑的表示法来提高速度,因为它需要在最少的位数上确定差异。另外,我想提到的是,如果可能的话,我希望在服务器端进行任何转换,这样就不必更改用户脚本(如果可能的话,用户端仍然应该在insert语句中传输一个字符串文字,而不是[部分]转换的值)

disbfnqx

disbfnqx1#

与我之前的说法相反,mysql的 UNHEX() 函数从一个字符串逐块进行转换,然后再进行concat,就像我前面提到的那样,因此该方法也适用于大于bigint的8字节限制的十六进制文本值。下面的示例表说明了这一点:

CREATE TABLE `testdb`.`tab` (
`hexcol_binary` BINARY(16) GENERATED ALWAYS AS (UNHEX(charcol)) STORED,
`charcol` CHAR(32) NOT NULL,
PRIMARY KEY (`hexcol_binary`));

主键是一个生成的列,因此对charcol的更新是与表进行交互的指定方式,该表具有来自外部的字符串文字:

REPLACE into tab (charcol) VALUES ('1010202030304040A0A0B0B0C0C0D0D0');
SELECT HEX(hexcol_binary) as HEXstring, tab.* FROM tab;

如图所示,在hexcolèu二进制文件上按预期构建键和索引。
要验证加速,请使用

ALTER TABLE `testdb`.`tab` 
ADD INDEX `charkey` (`charcol` ASC);
EXPLAIN SELECT * from tab where  hexcol_binary = UNHEX('1010202030304040A0A0B0B0C0C0D0D0') #keylength 16
EXPLAIN SELECT * from tab where charcol = '1010202030304040A0A0B0B0C0C0D0D0' #keylength 97

对hexcol\u二进制列的查找性能要好得多,特别是如果它的附加设置是唯一的。
注意:对于转换过程,十六进制转换并不关心十六进制字符a到f是否大写,但是charcol对此非常敏感。

相关问题