我想问一下mysql innodb你建议什么样的小数据库?
我没有innodb_file_per_table,但我不需要回收空间(看看我能节省多少空间会很高兴。)
大多数字符串都保存为utf8mb4。对于某些列,我可以使用latin1(我知道可能只有拉丁字符)。如果我将它们转换为latin1,你认为我可以节省很多空间吗?似乎这种变化也可以让你在搜索中获得性能提升。
我已经将具有大量文本的列定义为MEDIUMTEXT。如果我将该列定义为TEXT,您认为我应该节省一些空间吗? - 从我看到的这种类型就像VARCHAR(它只占用字符串的长度)
您还有其他建议吗?
数据库有超过3亿行,并存储在大约100G
中由于
答案 0 :(得分:1)
更改字符集无济于事。使用utf8或utf8mb4时,每个字符都以可变数量的字节存储。可存储在单个字节中的字符以这种方式存储。
从MEDIUMTEXT更改为TEXT无济于事。此类列中的每个字符串都以可变长度存储,最多只能存储您存储的字符串所需的长度。 TEXT可以存储高达64KB的字符串,MEDIUMTEXT可以存储高达16MB的字符串。我想每个这样的字符串可能需要一个长度指示符,每个TEXT两个字节,每个MEDIUMTEXT三个字节。因此,您可以在整个数据库中每列最多节省300MB(甚至可能不会那么多)。这不会产生足够的差异。
您可以了解表空间中有多少可用空间。运行SHOW TABLE STATUS LIKE 'sometable'
,其中“sometable”是表空间中任何表的名称。
返回的其中一个字段是data_free
。这是表空间中的可用空间(以字节为单位)。如果在同一个全局表空间中有多个表,则每个表都会报告相同的值。这并不意味着您的可用空间是所有这些数字的总和,它实际上是在每个表状态中重复的一个空闲空间。
为了节省空间,有些人用ROW_FORMAT=COMPRESSED
声明了InnoDB故事,但这要求你使用每表文件。由于您已在全局表空间中拥有表,即使将表重组为每个表的文件,也不会缩小全局表空间。当您将表移动到自己的文件中时,它只会留下一个大部分为空的巨大全局表空间。这样只会让您的存储问题变得更糟。
我唯一可以建议您执行以下步骤。在你这样做时,没有人可以使用你的数据库。
转储InnoDB表中的所有数据,必要时将转储输出保存到另一个卷。哪里有空间。您可以压缩转储的输出,如:
mysqldump ... | gzip -c > dump.sql.gz
停止你的mysqld进程。
rm /var/lib/mysql/ibdata1
,以及您可能仍然拥有的任何* .ibd文件。 当然,你应该先备份。 innodb_file_per_table
。同时启用innodb_file_format=Barracuda
,具体取决于MySQL的版本。ROW_FORMAT=COMPRESSED
。这显然需要很长时间才能转储并重新加载300M行。这将花费数小时,在此期间您的数据库将无法使用。
如果在执行此过程时无法使数据库不可用,则必须在副本上执行此操作,并且当过程完成且副本与主服务器同步时,您可以快速替换主人的复制品。在进行切换时,这仍然会导致短暂的服务中断,但速度很快。
下次开始使用更大的数据库服务器存储卷。计划您需要的存储量并为其计划。
重新评论,您已从MEDIUMTEXT更改为TEXT并节省了空间。
INFORMATION_SCHEMA中的大小(与SHOW TABLE STATUS报告的大小相同)只是估计值,它们可能已过时或以其他方式关闭。偶尔运行ANALYZE TABLE是一种更新统计信息的方法。
表格也可以分段,偶尔重建一次可以回收一些空间。使用OPTIMIZE TABLE。
另一种可能性是您的MEDIUMTEXT列实际上存储的文本字符串比TEXT列中的文本字符串长,并且ALTER TABLE会截断它们。
以下是演示:
mysql> create table m ( m mediumtext);
mysql> insert into m set m = repeat('X', 1024*1024*2);
Query OK, 1 row affected (0.05 sec)
mysql> select length(m) from m;
+-----------+
| length(m) |
+-----------+
| 2097152 |
+-----------+
mysql> alter table m modify column m text;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select length(m) from m;
+-----------+
| length(m) |
+-----------+
| 0 |
+-----------+
我在MEDIUMTEXT中填充了2MB的数据,然后使用ALTER将列更改为TEXT。它不是简单地截断到可以放入TEXT列的64KB,而是将文本截断为零个字符。
所以我希望您不要删除所有文本数据。