mysql - 复制 MySQL/MariaDB BLOB 列时会复制哪些数据?

标签 mysql blob mariadb sql-insert rdbms

table_1 创建如下:

CREATE TABLE table_1 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    some_blob BLOB
);

table_2 创建如下:

CREATE TABLE table_2 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    some_blob BLOB
);

我想知道的是,在我运行这个表复制查询之后

INSERT INTO table_2 (id, some_blob) SELECT id, some_blob FROM table_1;

table_1 表的每个 some_blob 字段中的实际文本是否会被复制并存储在磁盘上,或者数据库是否仅具有指向包含该内容的磁盘位置的重复指针BLOB 数据?

为什么 BLOB 复制必须涉及实际内容重复的一个论点如下:

Duplication of BLOB content is necessary because changes to BLOB data in table_1 should not also take place in table_2. If only the disk pointers were duplicated then content changes in one table would be reflected in the other table, which violates the properties of a correct copy operation.

现在我提出一种数据库可以实现的替代方法来满足此复制操作。这个替代方案表明上述论点不一定正确。数据库只能在执行给定的 INSERT 语句期间复制磁盘指针,然后每当发生试图修改其中一个表中的 BLOB 数据的 UPDATE 时,数据库然后才会在磁盘上分配更多空间来存储新数据,这是 UPDATE 查询的一部分。只有当不再存在任何指向它的磁盘指针时,BLOB 数据段才会被删除,并且特定的 BLOB 数据段可能有许多指向它的磁盘指针。

那么在执行给定的 INSERT 语句时,MySQL/MariaDB 使用哪种策略,还是使用不同的策略?

编辑:为什么我问这个问题

目前,我正在运行几个 UPDATE 查询,这些查询将大量 BLOB 数据从一个表复制到同一数据库中的另一个表(超过 1000 万行 BLOB 数据)。查询已经运行了一段时间。我很好奇性能如此缓慢是否是因为我比较的某些列索引不佳,因为这些查询实际上是复制内容而不是磁盘指针,或者可能是由于这两个原因。

我在问题的示例中使用了INSERT,因为这简化了我试图理解的数据库内部结构的概念。

最佳答案

每个表都有自己的 blob 数据副本以及所有其他数据。 MySQL 不进行数据浅复制。确实,blob 是单独分配的对象,但它们不在表之间共享。提供存储引擎内部的描述是为了让您了解正在发生的事情,而不是为了让您可以更改它(除非您 fork 存储引擎源并创建一个新版本......但首先让您的应用程序运行)。

因此,您的 UPDATE 查询正在删除旧的 blob 数据并写入新的。这是 I/O 密集型,因此可能很慢。

使用 INSERT 作为简化问题的方法是不正确的。将新的 blob 写入表比覆盖现有的 blob 更快。

在生产中最好的选择是避免更新 blob 列。

关于mysql - 复制 MySQL/MariaDB BLOB 列时会复制哪些数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51527743/

相关文章:

mysql - 将 .sql 文件批处理文件导入到 mariadb 失败

php - 从地址字段中拆分门牌号

mysql - 纬度和经度的正确 MySQL 多边形格式是什么?

javascript - HTML5 Canvas 压缩 DataURL() 输出比原始尺寸更大的尺寸

mysql - 简单的 SELECT 查询对于 ~4Gb 表 (MariaDB) 来说很慢

php - MariaDB 避免死锁

java - JPA 合并在刷新期间抛出异常键 'PRIMARY' 的重复条目

javascript - 返回未定义的 json 对象 [nodejs, fs]

php mysql 图片显示不正确

python - 使用 Python 在 MySQL 中保存 BLOBS