我目前正在设计一个数据库表,其中我们将有数亿条记录,我想知道什么是最好的管理方式。有了这些数据集,我们最终会遇到一些维护问题,比如表还原或alter表需要很长时间。现在我对如何处理这个问题有了一些想法,但也许有更好的办法?
由于我们的数据越新,相关性就越强,因此我们可以将其分为一个短时间范围(例如,过去30天)和旧数据集(过去30天以上)。为此,我认为有两种可能性:
把它分成两个分区,当前分区和旧数据分区
优势:
当前数据分区的表还原会很快,因为它没有那么大。在紧急情况下,我们会先恢复这个,然后用这些数据重新启动系统。对于用户来说,这是一个可以接受的场景
我们可以正常地读/写表,因此不需要特定的应用程序逻辑
缺点:
迁移脚本(alter table,我们可以在线使用,但如果我做得对的话,这并不适用于每个用例)需要很长时间,因为它们仍然在两个分区上运行。解决方案是让用户的旧数据分区脱机并在后台运行。因此用户在这段时间内不能访问旧数据,但这是可以的。有可能吗?
手动将其拆分为两个表,并使用夜间作业移动数据。ontop我们放置一个视图来选择数据
优势:
我们可以通过不再将旧数据表包含在视图中而使其脱机,并运行alter table脚本。完成后,将其放回视图中。因为用户再也找不到数据了,他也无法修改它
表还原会很快,因为我们会先还原当前表,更新视图并让用户再次使用它。旧数据表的恢复需要一段时间,但没关系
缺点:
既然是一个视图,我们只能通过它来选择。如果涉及到修改数据,我们需要为两个表编写更新查询,因为用户希望更新旧数据。因此从应用程序的角度来看,它需要自定义逻辑
所以我的问题是,在这种情况下,什么是最佳实践?你建议做什么?
谢谢
最佳答案
数亿是很多,但不是今天的大数据集。大型数据集有数十亿条记录。我想问题是,你的数据增长速度有多快?对它运行什么类型的查询?如果您的数据增长非常缓慢,任何数据库软件都可以足够快地处理这个数量,即使没有分区。如果它增长得很快,那么最好进行一些分区。
如果有oltp工作负载,那么小的查询具有很高的延迟,但是有很多查询,那么最好将热数据放在不同的位置。如果它们依赖于时间,我建议您使用基于datetime列的本机分区,按年份分区。这样,大多数基于最新数据的查询将只检查最新的分区,可能只检查整个数据集的一小部分。
如果最近是指很短的一个月,那么上述方法是不够的,尽管仍然有用。所以,可以在上面创建另一个热数据表。现在您有了一个按年划分的大数据表(总是所有数据),还有一个包含最新数据的小表。为了克服缺点,您可以这样做:
更新/插入/删除
所有查询都转到主表;如果需要,每个操作的触发器都将复制热数据表上的操作。(数据库级逻辑)
或者可以将相关查询发送到这两个表,并确保它们在应用程序级别(应用程序级别逻辑)中是一致的。这一个可能更高效,因为mysql触发器可以使数据库更慢。
select查询将根据查询转到新表,否则将转到主表(按年份划分有助于提高性能)。如果您想要灵活,也可以用代理进行查询拆分。Proxysql很容易处理。它还具有缓存和连接复用等其他优点。
若要从热数据表中丢弃旧数据,可以每天执行一个事件以删除超过1个月的记录。如果您有10万个要删除,您应该将它们以较小的块删除,以防止出现锁定、滞后和大量资源消耗等问题。另一种方法是使用is deleted列来标识过时的记录,并以此进行分区。随时删除分区是即时的。
对于非阻塞ddl操作,有一些开源工具可以在线迁移模式,而不会降低许多性能。查看pt-schema-change和ghost。
关于mysql - 大型数据集的数据库设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55311779/