让 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 intable_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/