1

我遇到了 .ibd MySQL 文件的问题。 场景: 我有一个 200GB 的 ubuntu 服务器,部署了一个 Django 应用程序并使用 MySQL 服务器。我的应用程序的性质是存储大量数据并对其进行一些 x 类型的处理。我有一张包含 5 到 600 万条数据记录的表。这个表已经获得了将近 60GB 的空间(tablename.ibd 文件占用的空间)。我尝试运行Optimize table tablename,但 .ibd 文件没有缩小。InnoDb 是真的。 问题

  • 首先,由于文件变得太大,存储空间即将耗尽。
  • 其次,当我尝试迁移迁移以在运行时在此表上添加列时,服务器空间不足,因为在运行迁移时 .ibd 文件开始变大,服务器最终空间不足。

如果有人帮助我解决这个问题,我将非常感激。 注意:(我无法从表中清除数据,因为数据对我来说非常重要)

(更新)

显示创建表表名

| Table         | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| table_name | CREATE TABLE `table_name` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `price` double DEFAULT NULL,
  `item_identifier` varchar(20) NOT NULL,
  `upc` varchar(20) DEFAULT NULL,
  `mpn` varchar(100) DEFAULT NULL,
  `weight` double DEFAULT NULL,
  `weight_unit` varchar(10) DEFAULT NULL,
  `main_category` varchar(50) DEFAULT NULL,
  `sub_category` varchar(50) DEFAULT NULL,
  `category_tree` varchar(500) DEFAULT NULL,
  `description` varchar(3800) DEFAULT NULL,
  `color` varchar(50) DEFAULT NULL,
  `brand` varchar(150) DEFAULT NULL,
  `main_image` varchar(2048) DEFAULT NULL,
  `secondary_images` varchar(255) DEFAULT NULL,
  `shipping` double,
  `stock` int(11) NOT NULL,
  `sale_rank` varchar(100) DEFAULT NULL,
  `itemHeight` double DEFAULT NULL,
  `itemLength` double DEFAULT NULL,
  `itemWeight` double DEFAULT NULL,
  `itemWidth` double DEFAULT NULL,
  `manufacturer` varchar(100) DEFAULT NULL,
  `product_model` varchar(150) DEFAULT NULL,
  `variations` longtext,
  `pack_count` int(11),
  `size` varchar(100) DEFAULT NULL,
  `flavor` varchar(100) DEFAULT NULL,
  `successfully_stored` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `item_identifier` (`item_identifier`),
  KEY `table_name_upc_3ca3d702` (`upc`)
) ENGINE=InnoDB AUTO_INCREMENT=7279139 DEFAULT CHARSET=latin1 |
+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

显示表状态,如 'tablename'\G

*************************** 1. row ***************************
           Name: table_name
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 7439966
 Avg_row_length: 8807
    Data_length: 65530740736
Max_data_length: 0
   Index_length: 323633152
      Data_free: 5242880
 Auto_increment: 7279139
    Create_time: 2021-06-11 21:26:17
    Update_time: 2021-06-12 18:08:06
     Check_time: NULL
      Collation: latin1_swedish_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.01 sec)
4

2 回答 2

2

InnoDB 磁盘空间是您想象的 2-3 倍。这是因为几个不同的“开销”事物。它们提供性能和功能;忍受它。

60GB / 5M = 每行 12KB。听起来你有一个更大的TEXT或更多的BLOB列?请提供SHOW CREATE TABLE,以便我们进一步讨论表格的布局。

OPTIMIZE TABLE很少有任何用处;不要费心使用它。)

尺寸

Bill 涵盖了大部分与大小相关的内容(DOUBLE->FLOAT等);唉,在您的情况下,它们只会将磁盘占用空间缩小几个百分点。

看来那variations一定是最笨重的列了。你从中得到SELECT AVG(LENGTH(variations)) FROM table_name;什么?我怀疑是几千。大多数“文本”可以很容易地通过标准压缩库进行 3:1 压缩。如果平均值为 3000,则潜在节省约为 2KB,大约是表格的 20-30%。(由于“非记录”存储机制,它可能会节省更多,但计算复杂。)

压缩单个列需要客户端的配合。也就是说,Django 中的代码需要对客户端和服务器之间的列进行压缩和解压缩。

UsingROW_FORMAT=COMPRESSED为整个表提供了大约 2:1 的压缩,并且对客户端是透明的。所以,总的来说,这可能更好。

正如比尔指出的那样,所有这些都是临时修复——随着表的增长,您耗尽磁盘空间。也就是说,优化、较小的数据类型和压缩只是临时修复。 你真的需要更多的磁盘空间。

于 2021-06-12T17:22:44.460 回答
1

获取具有更大存储量的服务器。

替代方案:获取第二台运行 MySQL 服务器的服务器,并将当前实例中的一些数据移动到该新实例。


重新更新表定义和状态:

表状态显示,数据长度,即行,使用约61 GiB,二级索引使用约0.3 GiB。因此,您不太可能通过删除索引来节省空间。

平均行大小为 8807 字节(这是一个估计值,它只是 data_length 除以行数)。您可以通过更改某些数据类型来稍微减小平均行大小。

例如,每个double占用 8 个字节。你能用floatornumeric(9,2)来获得足够的精度吗?这些每个占用 4 个字节。同样,有些int列可能能够smallint并且仍然存储您需要的值范围。

您应该阅读每种数据类型的存储要求,并决定如何最好地定义您的列。见https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html

可变长度数据类型就像varchar并且longtext已经存储了每行列中内容的长度,而不是允许的最大长度。因此,例如,如果其中的字符串已经短于 100 个字符,则将 varchar(200) 更改为 varchar(100) 不会有任何区别。

在某些情况下,varchar 可能会被对查找表的整数引用替换。与在每一行上重复相同的字符串相比,整数可能占用更少的空间。

您可以使用InnoDB COMPRESSED 行格式。根据您的数据,这会产生不同的结果,但它可能会将字符串缩小大约一半。

更改数据类型和行格式确实需要您运行 ALTER TABLE,因此需要有足够的存储空间临时用于表的副本,类似于运行 OPTIMIZE TABLE。如果您没有足够的空间来执行此操作,则无法更改表。

即使使用这些技术,您的表仍然会很大,并且随着我们在其中存储更多数据行,数据库往往会随着时间的推移而增长。即使您今天将其缩小一点,您仍然需要一个最终获得更大存储量的计划。

于 2021-06-12T15:41:10.133 回答