【问题标题】:Should I store BLOB length in my MySQL/MariaDB table?我应该将 BLOB 长度存储在我的 MySQL/MariaDB 表中吗?
【发布时间】:2020-12-31 08:03:46
【问题描述】:

我正在考虑将 BLOB 存储在我的 MariaDB 中,并在必要时将它们流式传输到基于 Web 的客户端。

我希望让客户端知道标头中响应的长度,这意味着在从数据库中读取整个内容之前,我需要文件长度。我可以想到两种方法来做到这一点:

  1. 将数据库中 blob 的长度存储在单独的列中
  2. SELECT OCTET_LENGTH(blob_field), blob_field FROM table WHERE id=?

我想知道那里的SELECT OCTET_LENGTH(blob_field)。数据库必须已经知道 blob 长度,但它的引擎实际上足够聪明,可以立即知道 OCTET_LENGTH(blob_field) 吗?或者引擎会在我每次执行SELECT 时读取整个 BLOB 字段并实际计算字节数(当然忽略缓存)?

【问题讨论】:

  • 我根据the code 强烈怀疑该blob 已被检索并完整传递给OCTET_LENGTH 函数。它不会逐字节计数,数字就在那里,但是如果函数需要,没有逻辑来延迟加载内容。我建议生成一个长度列。

标签: mysql mariadb blob


【解决方案1】:

在内部 BLOBS(和其他非固定长度类型)总是以长度存储,因此长度函数将访问长度信息(没有它,甚至不可能在不知道结尾的情况下逐字节遍历它们)。

由于 BLOB 的长度也在客户端/服务器协议中传输,因此您可以检索字段信息以获得正确的 blob 长度(请参阅 --column-info 输出的最大长度)

$ mysql test --column-type-info
MySQL [test]> create table t1 (id int, a blob);
Query OK, 0 rows affected (0.060 sec)

MySQL [test]> insert into t1 values (1, x'0003040003');
Query OK, 1 row affected (0.021 sec)

MySQL [test]> select a from t1 where id=1;
Field   1:  `a`
Catalog:    `def`
Database:   `test`
Table:      `t1`
Org_table:  `t1`
Type:       BLOB
Collation:  binary (63)
Length:     65535
Max_length: 5
Decimals:   0
Flags:      BLOB BINARY

【讨论】:

  • 此外,如果 BLOB 没有按照长度存储,则没有理由使用 TINYBLOBMEDIUMBLOBLONGBLOB。不同类型的 BLOB 将其长度编码为一个字节、两个字节、三个字节或四个字节。
  • @Bill:取决于存储引擎
  • 我认为除非提到特定的存储引擎,否则假设 InnoDB 是安全的,因为它多年来一直是 MySQL 的默认存储引擎。
  • InnoDB 的长度为 8 个字节,但无论 blob 类型如何,只使用最后 4 个字节。
  • 我明白了。这很有趣,我不知道。
【解决方案2】:

LENGTH(col) 给出八位字节长度。

如果这些 blob 很大,请考虑将它们作为文件放在服务器上,并使用其他机制让它们获取它们,例如 HTML 的 <img ...>

我假设您熟悉在发送字符串时如何对字符串进行转义?

我认为 HTTP 有一种机制来请求文件的一部分,给定一个字节偏移量和长度。 (我在 15 年前曾用它来下载视频,但我不记得细节了。)MySQL 可以提供 URL 和长度,然后客户端完成剩下的工作,而不需要 MySQL 做任何进一步的工作。

请记住,尽管 LONGBLOB 有 4GB 的限制,但还有其他一些东西(缓冲区等)使得处理大于 16MB 的东西变得很尴尬。

【讨论】:

  • 出于多种原因,我更喜欢数据库,主要是因为在这种集群环境中,没有“ 磁盘”。 HTTP Range 请求很好,但不是考虑因素,在这里。 BLOB 字段应该能够流式传输,而不是适合 16MiB 的数据包大小。我正在查看 Java API,以确保我尽可能地传达我的流媒体意图。有什么建议吗?
  • 我目前正在使用ResultSet.getBinaryStream(),但看起来ResultSet.getBlob().getBinaryStream() 可能会更好?我更喜欢前者,因为它更紧凑,但无论哪种方式,我都会看看 32MiB 文件会发生什么。
  • 看起来this answer 有一些很好的信息。我想我会坚持使用getBinaryStream
  • 如果没有令人发指的max_packet_size 值,这似乎实际上是不可能的。我正在尝试上传一个 > 16MiB 的测试文件,但无论我如何使用 API:流、blob 等,我都看不到让 Connector/J 和 MariaDB 接受它。我总是遇到max_packet_size 超出或max_long_data_size(已弃用并替换为max_packet_size)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-29
  • 2018-10-17
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2016-05-21
相关资源
最近更新 更多