如果我是一个innodb表,那么此查询将执行很多操作(一段时间内每秒一次,并附加少量数据)并且具有innodb_files_per_table = 0
会导致存储问题吗? Blob本身可能是2-3MB,但我丢失了30gb的数据使用量,并且想知道这段代码是否应归咎于我,或者我是否应该在其他地方查找。
SQL
UPDATE phppos_app_files
SET file_data = CONCAT(file_data, "NEW LINE OF DATA")
WHERE file_id = 10;
模式:
mysql> show create table phppos_app_files;
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_app_files | CREATE TABLE `phppos_app_files` (
`file_id` int(10) NOT NULL AUTO_INCREMENT,
`file_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`file_data` longblob NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`expires` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`file_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7577 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
博客列中存储的数据为2-3 mb的日志文本;只是纯文本。我要问的问题是,如果您从当前值开始连接的频繁更新查询是否导致存储问题,从而导致数据库出现严重问题。我只想确保它只存储最少的信息,并且concat更新是否会导致任何大的磁盘问题。
答案 0 :(得分:1)
在存储和访问BLOB时,频繁更新小数据块可能会由于碎片而浪费大量空间。有可能要考虑的优化方法:
innodb_file_per_table
不会缩小表空间。但是,它将回收由于碎片而丢失的空间,并将其标记为表空间内的可用空间:因此,它将在重新增长表空间之前重新利用任何空范围。答案 1 :(得分:1)
如果您频繁更新大型Blob,则确实确实可能会临时使用大量存储,并使表空间碎片化。
更新将原始数据页复制到“撤消日志”,该撤消日志只是表空间中的页面区域。如果您回滚事务并必须还原原始数据,InnoDB会保留这些复制的页面。提交更新后,不再需要撤消日志中的副本,并且InnoDB将逐渐清理。但是,如果您说的更新很频繁,则在InnoDB中清除垃圾的速度可能比InnoDB清除垃圾的速度快。
无论如何,为更多的撤消日志内容扩展存储空间将扩大表空间,即使在InnoDB清理后,表空间也不会缩小。它将始终保持其高水位线的大小。
为减轻这种情况,MySQL 5.6引入了一个选项,允许将撤消日志存储在系统表空间之外,而MySQL 5.7引入了一项功能,用于在清除撤消日志后将其截断。阅读https://dev.mysql.com/doc/refman/5.7/en/innodb-undo-tablespaces.html,以获取有关这些功能的更多信息。
如果您对InnoDB文件的内部布局感兴趣,建议您尝试使用开源工具Jeremy Cole写道:https://github.com/jeremycole/innodb_ruby/wiki
您可以转储ibdata1表空间中各种内容的摘要。许多文件可能尚未使用,但仍占用空间。
这是我本地MySQL沙箱中的一个示例。我只有一个带有innondb_file_per_table=0
的表(其他所有表都在中央表空间之外)。我运行了以下命令:
innodb_space -s /usr/local/var/mysql/ibdata1 -T mydatabase/mytable space-extents-illustrate
这是它创建的插图。图例(不包括在内)表明,我的一个表的数据和索引位于3008到3392之间的页面中。其他内容主要是InnoDB系统数据结构(黑色),系统表,插入缓冲区(深黄色)和空置的页(灰色)。
答案 2 :(得分:0)
您可以使用下面的查询来检查表的大小。这样,您可以看到哪个表浪费了您的存储空间。
SELECT
table_schema as `Database`,
table_name AS `Table`,
round(((data_length + index_length) / 1024 / 1024), 2) `Size in MB`
FROM information_schema.TABLES
ORDER BY (data_length + index_length) DESC
实际上,已使用的总空间保持不变。
如果使用innodb_files_per_table=0
,则只有一个表空间,并且由于数据变化很快,因此表空间可能会随时间碎片化。
如果您将来决定删除或截断表,则表空间大小将保持不变(不会缩小),因此无法从删除操作中重新获得空间。