通过自定义分区器对雪花中的大表进行分区

Posted

技术标签:

【中文标题】通过自定义分区器对雪花中的大表进行分区【英文标题】:Partitioning large table in snowflake through a custom partitioner 【发布时间】:2020-07-08 02:03:27 【问题描述】:

我们有一张雪花大表,里面有超过 550 亿条记录。用户通过提供 YEAR 和 SERIAL_NUMBER 作为谓词从该表中检索数据。检索记录需要大量时间。我们不想启用自动集群,因为这对我们来说变得昂贵。因此,我们提出了以下方法。我想对这种方法提出意见。

我们将表划分为多个分区。例如,如果表名是 TABLE_XYZ。我们正在为每年创建物理表,例如 TABLE_XYZ_2016、TABLE_XYZ_2017、TABLE_XYZ_2018、TABLE_XYS_2019、TABLE_XYZ_2020。最新的年份表经常更改,其他的基本保持不变。我们编写了一个分区器/拆分器,它读取源相似表并按年份拆分记录,并将它们加载到相应的年份表中,按年份和序列号排序。我们还在所有这些表格之上创建了一个视图。这个想法是需要所有年份的人会反对观点,对某一年感兴趣的人会反对物理年表。我们预计这将减少检索数据的时间。但是,如果有新的一年(比如说 2021 年),我们将不得不创建该表并重新定义视图。我还没有找到创建动态视图的方法。

如果这种方法有任何漏洞,请告诉我。

谢谢

【问题讨论】:

我相信,“内置”微分区和集群密钥也会做同样的事情。在日期列上创建集群键后,扫描将修剪那些以前的日期,直到这些以前的日期没有 DML。此外,自动刷新也仅适用于较新的日期。 【参考方案1】:

有一种更简单的方法可以使用集群键实现令人难以置信的性能。请参阅此处的文档:https://docs.snowflake.com/en/user-guide/tables-clustering-keys.html

总之,在 (YEAR, SERIAL_NUMBER) 上创建一个集群键,并且在后台 Snowflake 将根据这些键自动重新集群(排序)数据。最初,这可能会重新排序整个表,但随后,它只会重新排序新添加的值。

我对一个十亿行的表进行了测试,我在其中创建了一个唯一的序列,并在其上放置了一个集群键,通过键执行随机查找,每次获取都以毫秒为单位返回,只需一个 I/O。

Snowflake 在美国也有一个客户,其单个表中的数据超过 PETABYTE(是的,1,000 TB),该表使用相同的技术来实现对最近添加的数据的出色查询性能。

为了帮助调整性能,我建议(如果可能的话)加载 YEAR 格式的数据。 IE。如果您要进行几年的批量加载,请一次加载一年。否则别担心。

然后,您可以删除物理分区和视图,让 Snowflake 保持整个解决方案的清洁并自动更新。

您会发现后台集群在对数据进行排序时会产生初始成本,但随后应该会产生一些成本,而且性能提升值得付出努力。

【讨论】:

嗨,John,我们确实评估了这个选项,但对于我们的用例来说,这是一件代价高昂的事情。我们可能仍会进行自动重新聚类,但这仅适用于最新年份表,因为旧年份数据几乎没有变化 如果您的数据已经“自然聚类”,则重新聚类将不会花费任何成本,因为数据已经被聚类了。关于成本问题。估计替代解决方案的时间和费用。您可能会发现人员成本大大超过了对数据进行聚类的计算成本。【参考方案2】:

我认为没有任何数据库提供处理不存在的表的视图;)你可以做的是:

(最简单):创建 10 或 20 个空的“未来”表并将它们添加到您的视图中。它们将是空的,因此不会影响性能

(更难):创建一个将在年底某处运行的作业并创建新的年度表并重新创建视图

【讨论】:

谢谢,我喜欢这种方法。我试图从程序中做到这一点。这种方法将节省一些处理【参考方案3】:

如果加载到您的表中的历史记录不变,则重新集群表的成本将在第一个重新集群时最高。随着时间的推移,它应该会变得更便宜,对吧?

如果您出于某种原因不想使用自动重新集群,为什么不做您现在正在做的事情,而是将其放入单个表中?在您按yearSERIAL_NUMBER 排序的地方运行一系列选择查询并插入到新表中。对我来说,将其拆分为多个表是没有意义的。

【讨论】:

如果我在单个表上执行此操作,随着新数据插入最近一年,集群将再次变坏,对吧?

以上是关于通过自定义分区器对雪花中的大表进行分区的主要内容,如果未能解决你的问题,请参考以下文章

雪花分区与手动集群

apache spark中的自定义分区器

spark自定义分区器实现

重置为 Kafka 分区中的自定义偏移量

spark中的分区和自定义分区器中的重新分区和排序给出数组越界异常

[MapReduce_8] MapReduce 中的自定义分区实现