首页 > 解决方案 > 在 Snowflake 中使用内联值的视图

问题描述

我们有时通过使用子句提供内联值来创建带有小型静态数据集(值永远不会改变)的表/维度VALUES,如下所示(简化):

CREATE TABLE my_table
AS
SELECT * FROM VALUES
  (1, 2, 3),
  (4, 5, 6);

然而,一位同事刚刚意识到我们也可以将它们创建为相同的视图:

CREATE VIEW my_view
AS
SELECT * FROM VALUES
  (1, 2, 3),
  (4, 5, 6);

它有效,但我想知道使用视图而不是表的含义。我主要在寻找关于这是否是一个好主意以及为什么的任何社区/专家意见。只是想确保我们没有遗漏任何东西!

一些想法:

编辑:谢谢你的两个很好的答案!我希望我能接受两者。坚持使用桌子可能会更好。

标签: snowflake-cloud-data-platform

解决方案


对于像您的示例这样的小型数据集,表和(常量)视图之间的性能不会有太大差异。我们通常使用带有VALUESor的小数据集的子查询/CTE GENERATOR,它们通常性能足够。视图用法与子查询/CTE 非常相似,因此我不关心创建具有恒定视图的微小数据集。


相反,如果数据集很大,我更喜欢使用表而不是视图,因为表的性能要比视图好得多。

以下是视图可能比表性能更差的一些示例。请注意,这不是性能差异的唯一列表;可能存在其他情况/极端情况导致表和常量视图之间的性能差异。

在示例中,我将使用以下包含 10 亿个连续整数值的虚拟数据。这与在子句中列出 10 亿个值几乎相同VALUES(解析/编译的成本除外)。

create or replace table test_t1b (c1 int) as
select seq4() from table(generator(rowcount => 1000000000));

create or replace view test_v1b as
select seq4() c1 from table(generator(rowcount => 1000000000));

此外,我对所有示例都使用了 XSMALL 仓库。

(1) 分区剪枝不适用于常量视图

由于常量视图不是表,因此在运行查询时会生成值;它不能从分区修剪中受益。

select * from test_t1b where c1 < 1000;
-- 171 ms

select * from test_t1b where c1 = 1000;
-- 172 ms

select * from test_v1b where c1 < 1000;
-- 588 ms

select * from test_v1b where c1 = 1000;
-- 597 ms

在上面的例子中,对表 ( test_t1b) 的查询只扫描了 200+ 个分区中的 1 个分区,但对视图 ( test_v1b) 的查询总是要生成 10 亿行然后过滤。

(2) 元数据查询不适用于常量视图

Snowflake 可以在不执行查询的情况下从表元数据中获取多个函数(如MAX()MIN()和)的结果。COUNT()

然而,常量视图没有这样的元数据,所以函数总是必须从生成的数据集中计算结果。

select max(c1), min(c1), count(*) from test_t1b;
-- 45 ms

select max(c1), min(c1), count(*) from test_v1b;
-- 797 ms

总之,如果数据集只包含几行,那么您的分析是完全正确的;您可以随意使用视图来生成数据集。否则,将首选物理表,因为它受益于仅适用于物理表的各种优化。


推荐阅读