innodb 保存存储 space
innodb save storage space
我想问一下 mysql innodb 你有什么建议来获得一个更小的数据库?
我没有 innodb_file_per_table,但我不需要收回 space(如果能看到我能节省多少 space 就好了)。
大部分字符串保存为utf8mb4。对于某些列,我可以使用 latin1(我知道可能只有拉丁字符)。如果我将它们转换为 latin1,你认为我可以节省很多 space 吗?看来此更改也应该使您的搜索性能有所提高。
我已将包含大量文本的列定义为 MEDIUMTEXT 。如果我将该列定义为 TEXT,您认为我应该保存一些 space 吗? - 据我所知,这种类型的行为类似于 VARCHAR(它只占用字符串的长度)
您还有什么建议?
数据库3亿多行,存储在100G左右
谢谢
改变字符集也无济于事。当您使用 utf8 或 utf8mb4 时,每个字符都存储在可变字节数中。可以存储在单个字节中的字符以这种方式存储。
从 MEDIUMTEXT 更改为 TEXT 不会有太大帮助。此类列中的每个字符串都以可变长度存储,最多可达您存储的字符串所需的长度。 TEXT 最多可以存储 64KB 的字符串,MEDIUMTEXT 最多可以存储 16MB 的字符串。我想每个这样的字符串可能需要一个长度指示符,每个 TEXT 两个字节,每个 MEDIUMTEXT 三个字节。因此,您可能会在整个数据库中每列最多节省 300MB(甚至可能不会那么多)。这不会产生足够的影响。
您可以查看 tablespace 中有多少空闲 space。 运行 SHOW TABLE STATUS LIKE 'sometable'
其中 "sometable" 是您的 tablespace 中任何 table 的名称。
返回的字段之一是 data_free
。这是 tablespace 中以字节为单位的空闲 space。当您在同一个全局 tablespace 中有多个 table 时,每个 table 报告相同的值。这并不意味着您的免费 space 是所有这些数字的总和,它实际上是在每个 table 状态中重复的一个免费 space。
为了节省 space,有些人使用 ROW_FORMAT=COMPRESSED
声明 InnoDB 故事,但这需要您使用 file-per-table。由于您已经在全局 tablespace 中拥有 tables,即使您将 tables 重组为每个文件 table,它也不会t 缩小全局 tablespace。当您将 table 移动到它们自己的文件中时,它只会留下一个巨大的全局 tablespace,其中大部分是空的。这样只会让您的存储问题变得更糟。
我唯一可以建议您执行以下步骤。当您这样做时,没有人可以使用您的数据库。
从您的 InnoDB tables 中转储所有数据,必要时将转储的输出保存到另一个卷。哪里有space。您可以像这样压缩转储的输出:
mysqldump ... | gzip -c > dump.sql.gz
停止你的 mysqld 进程。
- 删除整个全局 tablespace,即
rm /var/lib/mysql/ibdata1
,以及您可能仍然拥有的所有 *.ibd 文件。 当然你应该先备份一下。
- 在您的 /etc/my.cnf 中启用
innodb_file_per_table
。还要根据 MySQL. 的版本启用 innodb_file_format=Barracuda
- 启动你的 mysqld 进程。它会自动重新创建全局 tablespace 作为一个新的小文件。
- 恢复您丢弃的 tables。它们将被放入单独的 InnoDB 文件中,而不是全局 tablespace.
- 如有必要,将每个 table 更改为使用
ROW_FORMAT=COMPRESSED
。
转储和重新加载 300M 行显然需要很长时间。这将花费很多时间,在此期间您的数据库将无法使用。
如果在执行此过程时无法使数据库不可用,则必须在副本上执行此操作,当该过程完成且副本与主服务器同步时,您可以快速用副本代替主副本。在您进行切换时,这仍然会导致服务短暂中断,但会很快。
下次开始为您的数据库服务器提供更大的存储容量。预测您需要的存储量并进行规划。
回复您的评论,您将 MEDIUMTEXT 更改为 TEXT 并保存了 space。
INFORMATION_SCHEMA 中的大小(与 SHOW TABLE STATUS 报告的大小相同)只是估计值,它们可能已过时或有其他偏差。 运行ning ANALYZE TABLE 偶尔更新统计信息的一种方式。
A table 也可以是碎片化的,偶尔重建它可以回收其中的一些 space。使用优化 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 |
+-----------+
我用 2MB 的数据填充了一个 MEDIUMTEXT,然后使用 ALTER 将列更改为 TEXT。它并没有简单地截断到可以放入 TEXT 列的 64KB,而是将文本截断为零个字符。
所以我希望你没有擦掉你所有的文本数据。
我想问一下 mysql innodb 你有什么建议来获得一个更小的数据库?
我没有 innodb_file_per_table,但我不需要收回 space(如果能看到我能节省多少 space 就好了)。
大部分字符串保存为utf8mb4。对于某些列,我可以使用 latin1(我知道可能只有拉丁字符)。如果我将它们转换为 latin1,你认为我可以节省很多 space 吗?看来此更改也应该使您的搜索性能有所提高。
我已将包含大量文本的列定义为 MEDIUMTEXT 。如果我将该列定义为 TEXT,您认为我应该保存一些 space 吗? - 据我所知,这种类型的行为类似于 VARCHAR(它只占用字符串的长度)
您还有什么建议?
数据库3亿多行,存储在100G左右
谢谢
改变字符集也无济于事。当您使用 utf8 或 utf8mb4 时,每个字符都存储在可变字节数中。可以存储在单个字节中的字符以这种方式存储。
从 MEDIUMTEXT 更改为 TEXT 不会有太大帮助。此类列中的每个字符串都以可变长度存储,最多可达您存储的字符串所需的长度。 TEXT 最多可以存储 64KB 的字符串,MEDIUMTEXT 最多可以存储 16MB 的字符串。我想每个这样的字符串可能需要一个长度指示符,每个 TEXT 两个字节,每个 MEDIUMTEXT 三个字节。因此,您可能会在整个数据库中每列最多节省 300MB(甚至可能不会那么多)。这不会产生足够的影响。
您可以查看 tablespace 中有多少空闲 space。 运行 SHOW TABLE STATUS LIKE 'sometable'
其中 "sometable" 是您的 tablespace 中任何 table 的名称。
返回的字段之一是 data_free
。这是 tablespace 中以字节为单位的空闲 space。当您在同一个全局 tablespace 中有多个 table 时,每个 table 报告相同的值。这并不意味着您的免费 space 是所有这些数字的总和,它实际上是在每个 table 状态中重复的一个免费 space。
为了节省 space,有些人使用 ROW_FORMAT=COMPRESSED
声明 InnoDB 故事,但这需要您使用 file-per-table。由于您已经在全局 tablespace 中拥有 tables,即使您将 tables 重组为每个文件 table,它也不会t 缩小全局 tablespace。当您将 table 移动到它们自己的文件中时,它只会留下一个巨大的全局 tablespace,其中大部分是空的。这样只会让您的存储问题变得更糟。
我唯一可以建议您执行以下步骤。当您这样做时,没有人可以使用您的数据库。
从您的 InnoDB tables 中转储所有数据,必要时将转储的输出保存到另一个卷。哪里有space。您可以像这样压缩转储的输出:
mysqldump ... | gzip -c > dump.sql.gz
停止你的 mysqld 进程。
- 删除整个全局 tablespace,即
rm /var/lib/mysql/ibdata1
,以及您可能仍然拥有的所有 *.ibd 文件。 当然你应该先备份一下。 - 在您的 /etc/my.cnf 中启用
innodb_file_per_table
。还要根据 MySQL. 的版本启用 - 启动你的 mysqld 进程。它会自动重新创建全局 tablespace 作为一个新的小文件。
- 恢复您丢弃的 tables。它们将被放入单独的 InnoDB 文件中,而不是全局 tablespace.
- 如有必要,将每个 table 更改为使用
ROW_FORMAT=COMPRESSED
。
innodb_file_format=Barracuda
转储和重新加载 300M 行显然需要很长时间。这将花费很多时间,在此期间您的数据库将无法使用。
如果在执行此过程时无法使数据库不可用,则必须在副本上执行此操作,当该过程完成且副本与主服务器同步时,您可以快速用副本代替主副本。在您进行切换时,这仍然会导致服务短暂中断,但会很快。
下次开始为您的数据库服务器提供更大的存储容量。预测您需要的存储量并进行规划。
回复您的评论,您将 MEDIUMTEXT 更改为 TEXT 并保存了 space。
INFORMATION_SCHEMA 中的大小(与 SHOW TABLE STATUS 报告的大小相同)只是估计值,它们可能已过时或有其他偏差。 运行ning ANALYZE TABLE 偶尔更新统计信息的一种方式。
A table 也可以是碎片化的,偶尔重建它可以回收其中的一些 space。使用优化 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 |
+-----------+
我用 2MB 的数据填充了一个 MEDIUMTEXT,然后使用 ALTER 将列更改为 TEXT。它并没有简单地截断到可以放入 TEXT 列的 64KB,而是将文本截断为零个字符。
所以我希望你没有擦掉你所有的文本数据。