大型数据集的数据库设计

时间:2019-03-23 07:54:36

标签: mysql database mariadb large-data database-partitioning

我目前正在处理一个数据库表,该数据库表中将有几亿条记录,我想知道什么是管理它的最佳方法。使用此类数据集,我们最终将遇到维护问题,例如,表还原或变更表将花费很长时间。现在我对如何处理有一些想法,但是也许有更好的方法?

由于我们的数据越新越相关,我们可以将其划分为较短的时间范围(例如最近30天)和旧的数据集(比最近30天还旧)。为此,我看到了两种可能性:

将其分为两个分区,即当前分区和旧数据分区

优势:

  • 由于当前数据分区的表还原不是很大,因此恢复速度很快。在紧急情况下,我们将首先还原此数据,然后仅使用该数据重新启动系统。这对于用户来说是可以接受的情况
  • 我们可以正常读取/写入表-因此不需要特定的应用程序逻辑

缺点:

  • 迁移脚本(更改表,我们可以在线使用,但是如果我正确的话,它不能在每个用例上都可以使用)需要很长时间,因为它们仍然针对两个分区运行。一种解决方案是使用户的旧数据分区脱机并在后台运行它。因此,在此期间,用户将无法访问旧数据,但是可以。这样可能吗?

手动将其拆分为两个表,并每夜进行一次移动数据。在顶部,我们放置了一个视图以选择数据

优势:

  • 我们可以使旧数据表脱机,方法是不再将其包含在视图中,然后运行alter table脚本。完成后,将其放回视图中。由于用户将不再找到数据,因此他也将无法对其进行修改
  • 表还原将很快,因为我们将首先还原当前表,更新视图并让用户再次使用它。恢复旧数据表需要一段时间,但没关系

缺点:

  • 因为它是视图,所以我们只能通过它进行选择。如果涉及到修改数据,我们将需要为两个表编写更新查询,因为用户希望更新旧数据。因此,从应用程序的角度来看,它需要自定义逻辑

所以我的问题是,在这种情况下最佳实践是什么?您建议做什么?

谢谢

2 个答案:

答案 0 :(得分:1)

数以亿计的数量很多,但对于今天的大数据集却不是。大型数据集拥有数十亿条记录。我的问题是,我认为,您的数据增长有多快?以及针对它运行的哪种查询?如果您的数据增长非常缓慢,那么任何数据库软件都可以即使没有分区,也要足够快地处理该数量。如果增长迅速,最好进行一些分区。

如果您有OLTP工作负载,那么这样的小查询具有很高的延迟,但是却有很多延迟,因此最好将热数据放在单独的位置。如果它们取决于时间,建议您使用基于datetime列的本机分区,并按年份进行分区。这样,大多数基于最新数据的查询将只检查最新分区,甚至可能检查整个数据集中的一小部分。

如果 recent 表示非常短的时间(如1个月),则上述方法虽然仍然有用,但还不够。因此,您可以在其顶部创建另一个 hot-data-table 。现在,您有一个按年份分区的大数据表(始终具有所有数据),还有一个具有最新数据的小表。要克服这些缺点,您可以执行以下操作:

  • 更新/插入/删除
  • 所有查询都转到主表;如有必要,每个操作的触发器将在热数据表上复制该操作。 (数据库级逻辑)
  • 或者您可以将相关查询发送到两个表,并确保它们在应用程序级别(应用程序级别逻辑)一致。这一功能可能会更高,因为mysql触发器会进一步降低数据库的速度。

  • SELECT查询将根据查询进入新表,否则将进入主表(按年进行分区有助于提高性能)。如果要灵活,也可以使用代理进行查询拆分。 Proxysql可以轻松应对。它还具有缓存和连接复用等其他优点。

  • 要丢弃热数据表中的旧数据,您可以每天执行一个事件以删除1个月以上的记录。如果要删除的数以万计,则应以较小的块删除它们,以防止出现锁定,滞后和大量资源消耗之类的问题。另一种方法是使用 is_deleted 列标识过时的记录,然后按此进行分区。随时可以删除分区。

对于非阻塞DDL操作,有一些开源工具可以在线迁移您的架构而不会降低性能。检出pt-schema-changeghost

答案 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无济于事。