这是我的问题“有效存储7.300.000.000行”(Efficiently storing 7.300.000.000 rows)的后续措施.
我决定将MySQL与分区配合使用,初步架构如下所示:
CREATE TABLE entity_values (
entity_id MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
date_id SMALLINT UNSIGNED DEFAULT 0 NOT NULL, # 2 bytes = [0 .. 65.535]
value_1 MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
value_2 MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
UNIQUE KEY (entity_id, date_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 PARTITION BY HASH(entity_id) PARTITIONS 25;
这给出:
>行= 7.300.000.000行(根据上一篇文章中所述的要求)
>大小/行= 11字节(3 2 3 3)
>总大小= 7.300.000.000行* 11字节= 80.300.000.000字节= 80.3 GB
>分区= 25(3.2 GB /分区,分区大小有些随意)
请注意,由于不使用“ id”列,因此我从原始设计中删除了主键.
现在,我的问题-鉴于我之前的文章中概述的要求和上面的架构,您对可以进行的进一步优化/调整有什么建议吗?还是鉴于我决定使用MySQL,以上架构是“最佳”的吗?
更新:我尝试将当前数据集加载到上面的架构中,而8.570.532行占用了价值212.000.000字节的磁盘空间,每行大约提供24.7字节.
更新:请注意,包含entity_id date_id的索引也将用于仅以entity_id为目标的查询.
解决方法:
我不太了解的一件事是您打算如何修剪数据.您每天有200万行,但尚未指定要保留多少数据.在某些时候,您将希望按年龄(完全有可能)使数据过期.
在这一点上,您将希望通过删除分区来实现,而不是通过执行删除操作来将每个分区锁定很长时间(因为它必须进行全表扫描以查找要删除的行),而不是执行删除操作由于分区上满是空洞,因此您的桌子不会变小.
按entity_id的散列进行分区对于搜索而言似乎是明智的,但是按时间进行分区可以简化修剪旧数据时的争用,这绝对是一件好事.
MyISAM具有一个称为“并发插入”的功能,您几乎肯定会一直使用它来实现并发和性能.这强制执行“禁止删除”规则,这意味着您只能通过删除分区来进行删除.
但是删除分区也很好,因为您可以收回磁盘空间.
综上所述,80G并没有那么大,我可能很想将它们全部存储在一个表中,并使用InnoDB启用并发访问.
哦,是的,如果您确实使用了InnoDB,则可以有一个主键object_id date_id,这意味着它将以相同的object_id聚集行.您可能希望在date_id上使用二级索引来启用有效的修剪.
请使用您的生产数据大小对此进行测试,并让我们知道您的发现!