变体列中唯一元素的雪花查询性能
Posted
技术标签:
【中文标题】变体列中唯一元素的雪花查询性能【英文标题】:Snowflake query performance on unique element in variant column 【发布时间】:2020-05-28 02:21:35 【问题描述】:我正在查询一个包含许多 TB 半结构化 json 数据的雪花视图。当我在感兴趣的变量列中查询在记录中不唯一的元素时,会在几秒钟内返回结果:
SELECT json_data:element1 FROM table WHERE json_data:common_category = 'CATEGORY1';
当我在感兴趣的变量列中查询一个在记录中唯一的元素时,运行时间会减慢到一些我尚未达到的不可接受的时间量:
SELECT json_data:element1 FROM table WHERE json_data:unique_id = 'ID123456';
我相信将唯一元素展平为变体列之外的关系形式会提高性能,但我不是拥有这些权限的 DBA。有没有办法调整我的查询,以便根据变量列 json 数据查找单个记录将产生可接受的性能?
【问题讨论】:
【参考方案1】:Snowflake 将内部变体 (json) 数据存储在一个独立的列式结构中,用于 100 多个最常见的元素,其余的存储在一个剩余的列中。这些虚拟列具有最小值/最大值,分布类似于普通列的统计信息。
notes 1 notes 2
这意味着在您的数据的主要列上,他们可以修剪大量不需要的分区以供读取(如果您的数据以某种方式自然排序,则有助于此)。
这也意味着,如果您使用 JSON 中的几列,它只会读取那些条纹,因此 IO 更少。
此外,当您像此处一样选择整个 blob 时,第二点不会起作用,因为 SELECT 的 READ 和 WHERE 的 READ 是相同的。
因此,对于您的查询,您将看到第一个查询全部包含少量分区。 对于您的第二个查询,您将看到它计划读取所有分区。
如果您将第一个查询更改为:
SELECT json_data:common_category FROM table WHERE json_data:common_category = 'CATEGORY1';
您会看到分区读取的数量与第一个示例相同,但读取的字节数应该是分数。
再次像普通表一样,您应该始终命名所有列并避免SELECT * FROM TABLE
,因为这样计划就知道要拉什么了。当您命名所有一阶列和所有变体列时,您将看到统计上更快的编译时间。
在加快速度的背景下:
如果你必须拥有所有 JSON 列然后
SELECT json_data FROM table WHERE json_data:common_category = 'CATEGORY1';
有可接受的速度然后做:
SELECT json_data:common_category FROM table WHERE json_data:unique_id = 'ID123456';
SELECT json_data FROM table WHERE json_data:common_category = <answer from prior> and json_data:unique_id = 'ID123456';
这样,第一个查询从所有分区中读取最少的数量,第二个是从必须读取的分区中读取所有..
现在,如果 common_category
的 unique_id = 'ID123456'
对所有分区都是通用的,那么现在这并不总是有效,但是如果所有行上都有其他列,它是顺序的或与数据的排序对齐(是您如何摄取数据,因此写入顺序,或者如果您将数据聚集在一起,您如何订购数据)。然后选择过滤列和排序列然后选择完全匹配排序列的聚焦效果。
我们有使用上述模式的非常相似的审计数据,以及我们存储在多个表中的其他数据,其中一些表是超级蒙皮和有序的(通过集群键),然后我们有一个键是 insert_time那个快速表和一个带有所有“额外”的宽/胖 json 表,这些表通常不使用,但以 _insert_time 顺序写入,因此在快速表中找到所需的数据允许读取具有减少分区的宽表。
【讨论】:
感谢您对选择显式变体元素名称的说明。这是否意味着由于条件元素的唯一性,没有其他方法可以提高我的第二个查询的性能?查询时间仍然慢得令人无法接受。SELECT json_data.column1 FROM table WHERE json_data:unique_id = 'ID123456';
将比SELECT json_data FROM table WHERE json_data:unique_id = 'ID123456';
更快,因为将拉出更少的列。但是有两个因素在起作用,即读取的分区数(或者更多的是可以排除在读取之外的分区数)和从这些分区读取的列数。
SELECT json_data:common_category FROM table WHERE json_data:unique_id = 'ID123456';
没有可接受的速度。任何时候添加unique_id
作为条件,查询都不会在合理的时间内运行。我已经通过选择 json_data 的单个显式元素编辑了我的问题,但我的问题保持不变。
我觉得我已经涵盖了这种情况,如果您使用 JSON 的 Minor 元素,您很可能会进行全表扫描,这将导致性能不佳。是的,将内容设置为“完整”列会在稀疏填充的列上提供更好的性能,但随后您的元数据会增加,您仍然可能会以全表扫描结束。
unique_id 列不是稀疏填充的。在 where 子句中运行带有 unique_id 的查询需要 > 8 分钟。您的回答似乎是不可能产生可接受的性能。我从来没有遇到过需要 8 分钟才能查询到关系列中的 id 的情况。以上是关于变体列中唯一元素的雪花查询性能的主要内容,如果未能解决你的问题,请参考以下文章