从 MySQL/MariaDB 打包并 to_base64 unix_timestamp 值

问题描述 投票:0回答:1

我在我正在使用的网站中的表中有一个日期时间列,我想经常将其用作键。

由于它将非常频繁地来回传输,我希望在不影响性能的情况下尽可能减少数据传输开销,并保持数据存储(最终在 cookie 中)的可靠性。

为此,我正在思考

to_base64(unix_timestamp(date_column))

然后我可以根据日期列的时间戳值将其转换为 Base64。例如,如果我的日期时间为

2024-11-02 07:25:16
,则其
unix_timestamp()
将为
1730528716
,其
to_base64()
MTczMDUyODcxNg==

现在的问题是,我认为费尽心思去获取一个

int(11)
值(至少到 2038 年 1 月中旬左右)只是为了将其打包为一串 0-9 的字符串是不公平的,而我可以正在转换其实际的整数表示形式。

如果我用

to_base64(unhex(hex(unix_timestamp())))
:

“破解”列,我可以从 MySQL 本身获得我想要的值
> select date_column, unix_timestamp(date_column), to_base64(unix_timestamp(date_column)), to_base64(unhex(hex(unix_timestamp(date_column))));
+---------------------+-----------------------------+----------------------------------------+----------------------------------------------------+
| date_column         | unix_timestamp(date_column) | to_base64(unix_timestamp(date_column)) | to_base64(unhex(hex(unix_timestamp(date_column)))) |
+---------------------+-----------------------------+----------------------------------------+----------------------------------------------------+
| 2024-11-02 07:25:16 |                  1730528716 | MTczMDUyODcxNg==                       | ZyXFzA==                                           |
+---------------------+-----------------------------+----------------------------------------+----------------------------------------------------+
1 row in set (0.000 sec)

因此,一方面,我在http服务器和mysql以及实际的客户端浏览器和http服务器以及base64计算中的每个客户端-服务器通信中节省了一些字节。但是通过上面的黑客,我非常怀疑我最终会真正保存任何东西......而我可以只是将整数值作为原始整数返回或进行(希望)快速转换。

我所做的一些其他尝试:

to_base64(convert(unix_timestamp(date_column) using binary))
to_base64(cast(unix_timestamp(date_column) as binary))
to_base64(cast(unix_timestamp(date_column) as int))
MTczMDUyODcxNg== (wrong)

我注意到通用值中也存在这种行为,例如:

select 10, to_base64(10), to_base64('10'), to_base64(unhex(hex(10)))
 10      | MTA=         | MTA=           | Cg==

(在这个例子中我没有保存角色FWIW)

那么,有没有什么便宜的方法可以从

unix_timestamp()
结果中获得base64“更短”的值?

由于这将在应用程序的关键部分中使用,因此只要从数字序列“转换”为实际数字表示的成本便宜,我拍摄的字符传输和计算越少,这是值得的。

如果最适合这种情况,我可能会考虑将日期存储为 unix 时间戳(不是

datetime
而是整数),这样我也可以从 64 位整数存储中受益。

mysql mariadb integer base64
1个回答
0
投票

首先解释为什么这些操作会导致有效负载变大,以及您的“黑客”如何提供帮助。

to_base64()
将其参数视为字符串,因此您的时间戳值 1730528716 隐式变为 10 个字符的字符串“1730528716”。

将整数转换为字符串总是会扩展输入,因为每个十进制数字代表大约 3 位信息,但 ASCII 字符串中的每个字符使用 8 位。

Base64 将任意三个 8 位字符的字符串转换为四个 6 位数字。但 ASCII 码中的数字字符仍占 8 位。因此,base64 总是将其字符串输入扩展 33%。

这就是为什么10个字符的字符串的base64编码是14个字节。

您所做的“黑客”是

unhex(hex())
,它将时间戳值转换为四个二进制字节而不是 10 个字符。二进制字节似乎是一个“字符串”,用于输入
to_base64()

这意味着它可以跳过到字符串的转换,并将 Base64 应用到四个字节而不是十个字节。

你问是否可以更快地完成

unhex(hex())
。您需要它到底有多快?这些已经是廉价的转换。在我的笔记本电脑上,我执行该操作 100 万次,但仍然需要不到 0.07 秒:

mysql> select benchmark(1000000, unhex(hex(1730528716))) as _result;
+---------+
| _result |
+---------+
|       0 |
+---------+
1 row in set (0.07 sec)

减少有效负载的另一个想法是存储少于完整的时间戳。您可以将其减少到小时的粒度,而不是以秒为单位存储时间戳。但这可能不适合您对时间戳的使用。

mysql> select length(unhex(hex(1730528716))) as ts_seconds_length,
  length(unhex(hex(round(1730528716/3600)))) as ts_hours_length;
+-------------------+-----------------+
| ts_seconds_length | ts_hours_length |
+-------------------+-----------------+
|                 4 |               3 |
+-------------------+-----------------+

时间戳还测量自 1970-01-01 纪元以来的秒数。如果您需要以秒为单位的时间戳,但您对那么早的时间戳不感兴趣,则只能计算自 2010 年以来的秒数。这会将时间戳减少到 9 位数字,而不是 10 位数字

mysql> select unix_timestamp('2024-11-02 07:25:16') - unix_timestamp('2010-01-01 00:00:00') as trunc_ts;
+-----------+
| trunc_ts  |
+-----------+
| 468224716 |
+-----------+
© www.soinside.com 2019 - 2024. All rights reserved.