高效的MySQL模式,具有对大型数据集进行分区的功能(7.300.000.000行和大约80 GB的数据)

这是我的问题“有效存储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上​​使用二级索引来启用有效的修剪.

请使用您的生产数据大小对此进行测试,并让我们知道您的发现!

上一篇:python – 以矢量化方式给出开始,停止数字的连接范围数组 – NumPy


下一篇:JavaScript性能优化?