0

我有如下表:我应该使用分区,在这种情况下

CREATE TABLE `connections` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`user_id_from` int(11) NOT NULL, 
`user_id_to` int(11) NOT NULL, 
`counter` int(11) NOT NULL, 
PRIMARY KEY (`id`), 
UNIQUE KEY `to_from` (`user_id_to`,`user_id_from`), 
KEY `user_id_from` (`user_id_from`) 
) ENGINE=InnoDB AUTO_INCREMENT=1559108041 DEFAULT CHARSET=utf8 

这是103GB(43GB的数据和59GB指数)和大约〜1143663061行。我认为主要的性能障碍是索引大小的结果,因此解决方案可能意味着将其减小为小型索引(分区)。我正在考虑添加一个DATE字段,并按月进行分区。每次只能查询最近的X个月(X将在6左右),我可以忍受。我看到的骗局是这会导致桌子变得比现在更大。

在我测试基准之前,你会推荐这个吗?你有其他建议吗?

更新: 我使用这个表的查询:
SELECT * FROM connections WHERE user_id_to=x LIMIT 3000
SELECT * FROM connections WHERE user_id_from=x ORDER BY counter DESC LIMIT 100
SELECT user_id_from, counter FROM connections WHERE user_id_to IN (x1, x2, ..., x1000) LIMIT 500
SELECT * FROM connections WHERE user_id_to=x AND user_id_from IN (x1, x2, ..., x1000) LIMIT 1000

我通过user_id_to为主要条件,也user_id_from为主要查询的原因条件,是否有连接是有方向性的,并且我正在寻找相互连接(从→到>从& &从 - >到)。 WHERE user_id_to的行数可能会非常高,因为WHERE user_id_from大多不是那么多,这就是为什么当我ORDER BY counter我没有为此添加索引时。

+0

查看下面的答案可能会删除您的索引之一。另外,奇怪的是你会有'_from'和'_to'和INT字段而不是日期字段。在整个表格中保持它们的独特性意味着没有两个用户可以有相同的开始和结束日期,这也很奇怪。 – aneroid

+0

_“在我测试基准之前...” - - 您应该首先对**进行基准测试,并确定确切的查询速度缓慢(以及它们的计时和执行计划)。替代键“id”是否有[特定原因](http://stackoverflow.com/tags/surrogate-key/info)?如果不是,则可以忽略它,并使用'{user_id_to,user_id_from}'作为主键,从而减少所需的存储空间。除此之外,我怀疑'{user_id_from,user_id_to}'上的复合索引可能比单独使用'{user_id_from}'更好。但所有这些都是猜测而不知道你的疑问。 –

+0

@BrankoDimitrijevic有趣的想法删除代理键。它没有任何特定的原因,但是在某些情况下我发现它们很有用(例如,当想要以块的形式迭代表格时)。 '{user_id_from,user_id_to}'索引不会比'{user_id_from}'大吗?你为什么怀疑它会为我提供更好的服务?有关分区选项的任何想法? – Noam

回答

0

你可以通过修改唯一键(取决于您的查询如何使用它们)删除一个索引user_id_from:与其to_from,使其from_to(user_id_from,user_id_to),像始端。那么您将不需要0​​上的第二个索引,因为即使第二部分不是必需的(user_id_to),也可以使用第一部分组合索引/键user_id_from

所以你只需要:

PRIMARY KEY (`id`) 
UNIQUE KEY `from_to` (`user_id_from`,`user_id_to`) 

这是一个变化,以节省索引使用的空间。 (使用表的一小部分进行测试,并查看EXPLAIN结果)。 PS:当您继续进行此更改时,请删除user_id_*索引,然后创建from_to索引,以防您的磁盘限制超过30 GB。

具体到你的问题...
如果旧的数据将不再需要,它可能更有意义之一:

  1. 删除旧行,当user_id_to超过1年以前等;或者,
  2. (带选项1) - 创建一个表,如old_users,只需添加其ID和user_id_to字段,如果您需要该信息。
  3. connections_archive等新表格中插入旧行connections,然后从connections中删除。假设您在应用程序的查询中不会查询_archive,或者只从管理界面(即很少)查询_archive,在这种情况下,会遇到connectionsconnections_archive的“联合”查询性能问题。
+0

我已经更新了这个表格上运行的查询的问题,如果我错了,请更正我的错误,但我假设您的解决方案不包含像我需要的WHERE user_id_to = x这样的查询。 – Noam

+0

你是对的,我以为你不会有一个只使用'user_id_to'而没有'user_id_from'的查询。因此,我建议复合'{user_id_from,user_id_to}'而不是to-from。 Branko的一些评论可能会更好地解决你的问题。 – aneroid

相关问题