mysql - 将base64编码的数据存储为BLOB或TEXT数据类型

标签 mysql text blob innodb

我们有一个MySQL InnoDB表,其中包含约10列由base64编码的小型javascript文件和由base64编码的png(小于2KB大小)图像。

插入的次数很少,但读取次数却很多,但是输出会在Memcached实例上缓存几分钟,以避免后续的读取。

现在,我们正在为这些列使用BLOB,但是我想知道在性能或快照备份方面切换到TEXT数据类型是否有优势。

我的搜索结果表明,针对我的情况的BLOBTEXT几乎相同,并且由于我事先不知道实际上将存储的数据类型,因此我选择了BLOB

您是否有针对此特定案例的TEXT vs BLOB辩论的任何指针?

最佳答案

一个人不应该在自己的数据库中存储Base64编码的数据...
Base64是一种编码,其中仅使用可打印的文本字符表示任意二进制数据:它设计用于需要在只能处理可打印文本(例如SMTP /电子邮件)的协议(protocol)或介质上传输此类二进制数据的情况。它增加了数据大小(增加了33%)并增加了编码/解码的计算成本,因此,除非绝对必要,否则应避免这样做。
相比之下,就是BLOB列的全部要点,就是它们存储了不透明的二进制字符串。因此,只需继续将您的内容直接存储到BLOB列中,而无需首先对其进行Base64编码。 (也就是说,如果MySQL对于要存储的特定数据具有更合适的类型,则您可能希望使用它:例如,像JavaScript源这样的文本文件可以从存储在TEXT列中受益,MySQL会针对这些列本地跟踪特定于文本的数据元数据-有关详情,请参见下文)。
SQL数据库需要可打印文本编码(如Base64来处理任意二进制数据)的(错误)想法已经被大量不了解情况的教程所延续。这个想法似乎被误认为是错误的信念,因为SQL在其他上下文中仅包含可打印文本,因此它肯定也必须对二进制数据(至少对数据传输(如果不是对数据存储)要求它)。事实并非如此:SQL可以通过多种方式传递二进制数据,包括纯字符串文字(前提是它们像其他字符串一样被正确地引号和转义)。当然,将数据(任何类型)传递到数据库的首选方法是通过参数化查询,并且参数的数据类型可以像其他任何东西一样轻松地成为原始二进制字符串。
...除非出于性能原因将其缓存...
从Base64编码的数据中存储可能会带来一些好处的唯一情况是,通常在从数据库中检索到数据后立即通过需要这种编码的协议(protocol)(例如,通过电子邮件附件)传输该数据,在这种情况下,存储Base64编码的数据表示将避免每次获取时都必须对其他原始数据执行编码操作。
但是,请注意,从这种意义上讲,Base64编码的存储仅充当缓存,就像出于性能原因可能存储非规范化数据一样。
...在这种情况下,应该是TEXT而不是BLOB如上所述,TEXTBLOB列之间的唯一区别是,对于TEXT列,MySQL还会为您跟踪特定于文本的元数据(例如字符编码和排序规则)。这个额外的元数据使MySQL能够在存储和连接字符集之间转换值(如果适用),并执行花式字符串比较/排序操作。
一般而言:如果两个使用不同字符集的客户端应该看到相同的字节,则需要BLOB列;如果他们应该看到相同的字符,则需要一个TEXT列。
使用Base64,这两个客户端最终必须找到将数据解码为相同的字节。但是他们应该看到存储/编码的数据具有相同的字符。例如,假设有人希望插入'Hello world!'(即'SGVsbG8gd29ybGQh')的Base64编码。如果插入的应用程序以UTF-8字符集工作,则它将字节序列0x53475673624738676432397962475168发送到数据库。

  • (如果该字节序列存储在BLOB列中,然后由运行在UTF-16 *中的应用程序检索),则将返回相同的字节-代表'升噳扇㡧搲㥹扇全',而不是所需的Base64编码值;而
  • (如果该字节序列存储在TEXT列中,然后由运行在UTF-16中的应用程序检索,则MySQL会即时进行转码以返回字节序列0x0053004700560073006200470038006700640032003900790062004700510068,它代表原始Base64编码的'SGVsbG8gd29ybGQh'为想要的。

  • 当然,您仍然可以使用BLOB列并以其他方式跟踪字符编码-但这将不必要地重新发明轮子,从而增加了维护复杂性并带来了意外错误的风险。

    *实际上,MySQL不支持使用与ASCII字节不兼容的客户端字符集(因此,Base64编码在它们的任何组合中始终保持一致),但是该示例仍然用于说明BLOBTEXT列类型之间的区别从而解释了为什么TEXT在技术上是正确的,即使BLOB实际上可以正常工作(至少在MySQL添加对非ASCII兼容客户端字符集的支持之前)。

    关于mysql - 将base64编码的数据存储为BLOB或TEXT数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14042599/

    相关文章:

    java - 从 BLOB 数据类型转义特殊字符

    php - 如何使用其他信息在php中上传图像

    mysql - 无法选择列名 int

    php - 返回奇怪的 POST 数据垃圾

    python - 如何在 tkinter 文本小部件中突出显示文本

    javascript - 有谁知道如何用javascript更改文本字段插入符的字符?

    mysql - 保存不带 Null 的模型值

    php - Mysql php计算两个表的总价

    java - Android 如何修剪字符串中的多行?

    java.io.StreamCorruptedException : invalid stream header: 626F6775 using mysql blob, java对象和自定义对象