我目前正在处理一个数据库表,该数据库表中将有几亿条记录,我想知道什么是管理它的最佳方法。使用此类数据集,我们最终将遇到维护问题,例如,表还原或变更表将花费很长时间。现在我对如何处理有一些想法,但是也许有更好的方法?
由于我们的数据越新越相关,我们可以将其划分为较短的时间范围(例如最近30天)和旧的数据集(比最近30天还旧)。为此,我看到了两种可能性:
将其分为两个分区,即当前分区和旧数据分区
优势:
缺点:
手动将其拆分为两个表,并每夜进行一次移动数据。在顶部,我们放置了一个视图以选择数据
优势:
缺点:
所以我的问题是,在这种情况下最佳实践是什么?您建议做什么?
谢谢
答案 0 :(得分:1)
数以亿计的数量很多,但对于今天的大数据集却不是。大型数据集拥有数十亿条记录。我的问题是,我认为,您的数据增长有多快?以及针对它运行的哪种查询?如果您的数据增长非常缓慢,那么任何数据库软件都可以即使没有分区,也要足够快地处理该数量。如果增长迅速,最好进行一些分区。
如果您有OLTP工作负载,那么这样的小查询具有很高的延迟,但是却有很多延迟,因此最好将热数据放在单独的位置。如果它们取决于时间,建议您使用基于datetime列的本机分区,并按年份进行分区。这样,大多数基于最新数据的查询将只检查最新分区,甚至可能检查整个数据集中的一小部分。
如果 recent 表示非常短的时间(如1个月),则上述方法虽然仍然有用,但还不够。因此,您可以在其顶部创建另一个 hot-data-table 。现在,您有一个按年份分区的大数据表(始终具有所有数据),还有一个具有最新数据的小表。要克服这些缺点,您可以执行以下操作:
或者您可以将相关查询发送到两个表,并确保它们在应用程序级别(应用程序级别逻辑)一致。这一功能可能会更高,因为mysql触发器会进一步降低数据库的速度。
SELECT查询将根据查询进入新表,否则将进入主表(按年进行分区有助于提高性能)。如果要灵活,也可以使用代理进行查询拆分。 Proxysql可以轻松应对。它还具有缓存和连接复用等其他优点。
要丢弃热数据表中的旧数据,您可以每天执行一个事件以删除1个月以上的记录。如果要删除的数以万计,则应以较小的块删除它们,以防止出现锁定,滞后和大量资源消耗之类的问题。另一种方法是使用 is_deleted 列标识过时的记录,然后按此进行分区。随时可以删除分区。
对于非阻塞DDL操作,有一些开源工具可以在线迁移您的架构而不会降低性能。检出pt-schema-change和ghost。
答案 1 :(得分:0)
(着眼于旧数据还是新数据)
如果该表是按时间顺序排序的,并且您主要访问“新”数据,则将自动建立大量的缓存及其所提供的性能。
只需确保使用InnoDB并将PRIMARY KEY
设为AUTO_INCREMENT
(或以DATETIME
开头)。
让我们运行一些数字。如果表中有300M行,并且每行占用100个字节(简单的经验法则),则表的数据占用30GB。索引和其他表将有更多内容。如果您在具有64GB RAM的服务器上运行(今天并非不合理),则所有内容都可以放入RAM中并且不需要太多I / O。
相反,如果您只有8GB的RAM,而大多数活动位于表的最新10%中,那么它将再次得到很好的缓存。
(注意:I / O是性能中最大的硬件组件。)
通常使大型表设计崩溃的是索引,查询表述甚至整个体系结构。但是,由于您对此没有详细信息,因此我跳过了。
您提到了一种粗略的手动分区表的方法。内置了一些内容:PARTITIONing
。但这不可能可能有助于插入,更新或选择,因此我不建议您进行一些进一步的讨论。
如果您最终将清除“旧”数据(例如一年后),那么PARTITIONing
是个好主意。如果表仅保存1年的数据,我将使用每周分区。如果您需要,我们可以进一步讨论。 但是请注意,唯一的好处是可以通过DROP PARTITION
删除旧数据;分区是。
SUBPARTITIONs
无济于事。