优化MySQL表结构和行大小的影响

时间:2014-03-16 13:09:16

标签: mysql sql innodb

我的一个数据库表已经变得非常大,我认为它会影响我网站的性能(这肯定会使备份速度慢很多)。

它有大约13,000,000行,大小为4.2 GiB,其中1.2 GiB是数据。

结构如下:

CREATE TABLE IF NOT EXISTS `t1` (
  `id` int(10) unsigned NOT NULL,
  `int2` int(10) unsigned NOT NULL,
  `int3` int(10) unsigned NOT NULL,
  `int4` int(10) unsigned NOT NULL,
  `char1` varchar(255) NOT NULL,
  `int5` int(10) NOT NULL,
  `char2` varchar(1024) DEFAULT NULL,
  `char3` varchar(1024) NOT NULL,
  PRIMARY KEY (`id`,`int2`,`int3`,`int4`),
  KEY `key1` (`id`,`int2`,`char1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

此表中的常见操作是插入和选择,行永远不会更新,很少删除。 int2是一个正在运行的版本号,这意味着通常只选择该ID为int2值最高的行。

我一直在考虑几种优化方法,我想知道哪一种方法可以追求:

  1. char1(在索引中)实际上只包含大约40,000个不同的字符串。我可以将字符串移动到第二个表(idchar - > char)中,然后将id保存在我的主表中,代价是在插入和选择期间额外的id查找步骤。
  2. char2和char3通常是空的。我可以将它们移动到一个单独的表中,然后我将在选择中进行LEFT JOIN。
  3. 即使char2和char3包含数据,它们通常也短于1024个字符。我可能会将这些缩短到~200。
  4. 您认为哪一个最有希望?在MySQL InnoDB表中减小行大小(通过使char1成为整数或通过删除/调整列大小)实际上对性能有很大影响吗?

    由于

2 个答案:

答案 0 :(得分:2)

有几种选择。根据你的说法,将char1移动到另一个表似乎很合理。在某些情况下,额外查找甚至可能比将原始数据存储在表中更快。 (当重复的值导致表大于必要时,会发生这种情况,特别是当较大的表可能大于可用内存时。)并且,这将节省数据表和相应索引中的空间。

如果不了解有关系统和查询负载的更多信息,很难说对性能的确切影响。

char3char4移动到另一个表格的影响微乎其微。链接到另一个表的开销会占用空间的任何增益。通过将它们存储为varchar(255)而不是varchar(1024),您可以为每条记录保存几个字节。

如果您有自然分区键,那么分区绝对是一种选择,特别是减少备份时间。这对于事务样式表非常方便,在该表中插入记录并且永远或很少修改。另一方面,如果记录包含客户记录,并且任何记录都可以随时修改,那么您仍然需要备份所有分区。

答案 1 :(得分:1)

有几个因素可能会影响数据库的性能。分区是最佳选择,但并非总是可以完成。如果在插入之前搜索char1,则分区可能是一个问题,因为您必须搜索所有部分以获取密钥。您必须分析数据的生成方式,最重要的是如何为此表生成查询。这是关键所以你应该在这个表上发布你的查询。在char2和char3的情况下,移动到另一个表将没有任何区别。您还应该提到数据的物理分布。您使用的是单个数据文件吗?数据文件与SO在同一物理磁盘上吗?提供更多详细信息,以便我们为您提供更多帮助。