让 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
表将被复制并存储在磁盘上,或者db将只有指向包含blob数据的磁盘位置的复制指针?
为什么blob复制必须涉及实际内容的复制,有一个理由如下:
有必要复制blob内容,因为中的blob数据发生了更改 table_1
不应该也发生在 table_2
. 如果只复制磁盘指针,则一个表中的内容更改将反映在另一个表中,这违反了正确复制操作的属性。
现在,我提供了一种db可以实现的替代方法来满足这个复制操作。这个替代方案表明,上述论点不一定是正确的。db只能在给定的执行过程中复制磁盘指针 INSERT
声明,然后 UPDATE
如果要修改其中一个表中的blob数据,则db只会在磁盘上分配更多空间来存储作为该表一部分的新数据 UPDATE
查询。一个blob数据段只有在不再存在指向它的磁盘指针时才会被删除,而一个特定的blob数据段可能有许多指向它的磁盘指针。
那么mysql/mariadb在执行给定的 INSERT
声明,还是使用不同的策略?
编辑:我为什么问这个问题
目前我正在运行几个 UPDATE
将大量blob数据从一个表复制到同一数据库中的另一个表的查询(超过1000万行blob数据)。查询已经运行了一段时间。我很好奇,性能之所以如此之慢,是因为我比较的一些列的索引很差,是因为这些查询实际上是在复制内容而不是磁盘指针,还是因为这两个原因。
我用一个 INSERT
因为这简化了我试图理解的数据库内部的概念。
1条答案
按热度按时间s6fujrry1#
每个表都有自己的blob数据和所有其他数据的副本。mysql不做数据的浅层复制。blob确实是单独分配的对象,但它们不在表之间共享。提供存储引擎内部的描述是为了让您能够理解正在发生的事情,而不是为了您能够更改它(除非您派生存储引擎源代码并创建新版本。。。但先让你的应用程序工作)。
因此,更新查询将删除旧的blob数据并写入新的blob数据。这是i/o密集型的,所以可能很慢。
使用insert简化问题是不正确的。向表中写入新的blob比覆盖现有blob更快。
在生产中最好的办法是避免更新blob列。