首页 > 解决方案 > 复制 MySQL/MariaDB BLOB 列时复制了哪些数据?

问题描述

让我们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;

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

关于为什么 BLOB 复制必须涉及复制实际内容的一个论据,原因如下:

BLOB 内容的复制是必要的,因为对 BLOB 数据的更改table_1也不应该在table_2. 如果仅复制磁盘指针,则一个表中的内容更改将反映在另一个表中,这违反了正确复制操作的属性。

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

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

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

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

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

标签: mysqlblobmariadbsql-insertrdbms

解决方案


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

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

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

您在生产中的最佳选择是避免对 blob 列进行更新。


推荐阅读