Snowflake - 缓存


Snowflake有一个独特的缓存功能。基于此缓存,它可以通过更少的数据扫描提供快速且快速的结果。它甚至还可以帮助客户减少账单。

Snowflake 中的缓存基本上分为三种类型。

  • 元数据缓存
  • 查询结果缓存
  • 数据缓存

默认情况下,所有Snowflake会话都启用缓存。但用户可以根据自己的需要禁用它。但是,用户只能禁用查询结果缓存,但无法禁用元数据缓存数据缓存

在本章中,我们将讨论不同类型的缓存以及Snowflake如何决定缓存。

元数据缓存

元数据存储在云服务层,因此缓存也在同一层。这些元数据缓存始终为每个人启用。

它基本上包含以下详细信息 -

  • 表中的行数。

  • 列的最小值/最大值

  • 列中不同值的数量>

  • 列中 NULL 值的数量

  • 不同表版本的详细信息

  • 物理文件参考

这些信息基本上被 SQL 优化器用来执行得越来越快。可能存在一些可以由元数据本身完全回答的查询。对于此类查询,不需要虚拟仓库,但可能会收取云服务费用。

这样的查询就像 -

  • 所有 SHOW命令

  • MIN、MAX,但仅限于列的整数/数字/日期数据类型。

  • 数数

让我们运行一个查询来查看元数据缓存如何工作以及用户如何验证。

登录 Snowflake 并转到工作表。通过运行以下查询来暂停仓库 -

ALTER WAREHOUSE COMPUTE_WH SUSPEND;

现在,按顺序运行以下查询 -

USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF100;
SELECT MIN(L_orderkey), MAX(l_orderkey), COUNT(*) FROM lineitem;

用户将能够在不到 100 毫秒的时间内看到结果,如下面的屏幕截图所示。单击查询 ID。它将显示查询 ID 的链接。然后单击如下所示的链接 -

查询编号

默认情况下,它会打开提及 SQL 的详细信息页面。单击配置文件选项卡。它显示 100% 基于元数据的结果。这意味着在没有任何计算仓库的情况下,它可以运行结果并根据元数据缓存获取详细信息。

以下屏幕截图显示了上述步骤 -

轮廓

查询结果缓存

查询结果由云服务层存储和管理。如果同一个查询运行多次,但条件是基础数据或基表在查询必须运行多次的时间段内没有更改,那么它非常有用。此缓存具有独特的功能,可供同一帐户内的其他用户使用。

例如,如果 user1 第一次运行查询,结果将存储在缓存中。当 user2 也尝试运行相同的查询时(假设基表和数据未更改),它会从查询结果缓存中获取结果。

缓存的结果 24 小时内可用。但是,每次重新运行同一查询时,24 小时计数器都会重置。例如,如果查询在上午 10 点运行,则其缓存将一直可用到第二天上午 10 点。如果同一查询在同一天下午 2 点重新运行,则缓存将一直可用到第二天下午 2 点。

使用查询结果缓存需要满足一些条件 -

  • 应重新运行完全相同的SQL查询。

  • SQL 中不应有任何随机函数。

  • 用户必须有正确的权限才能使用它。

  • 运行查询时应启用查询结果。默认情况下,它是启用的,除非另有设置。

查询结果缓存的一些情况是 -

  • 查询那些需要大量计算的查询,例如聚合函数和半结构化数据分析。

  • 那些运行非常频繁的查询。

  • 查询这些很复杂。

  • 重构另一个查询的输出,例如“USE TABLE function RESULT_SCAN(<query_id>)”。

让我们运行一个查询来看看查询结果缓存如何工作以及用户如何验证。

登录 Snowflake 并转到工作表。通过运行以下查询恢复仓库 -

ALTER WAREHOUSE COMPUTE_WH Resume;

现在,按顺序运行以下查询 -

USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF100;
SELECT l_returnflag, l_linestatus,
SUM(l_quantity) AS sum_qty,
SUM(l_extendedprice) AS sum_base_price,
SUM(l_extendedprice * (l_discount)) AS sum_disc_price,
SUM(l_extendedprice * (l_discount) * (1+l_tax)) AS sum_charge,
AVG(l_quantity) AS avg_qty,
AVG(l_extendedprice) AS avg_price,
AVG(l_discount) AS avg_disc,
COUNT(*) AS count_order
FROM lineitem
WHERE l_shipdate <= dateadd(day, 90, to_date('1998-12-01'))
GROUP BY l_returnflag, l_linestatus
ORDER BY l_returnflag, l_linestatus;

单击查询 ID。它将显示查询 ID 的链接。然后单击前面示例(元数据缓存)中所示的链接。检查查询配置文件,它将显示如下所示 -

查询资料

它显示 80.5% 的数据已扫描,因此不涉及缓存。通过运行以下查询来暂停仓库 -

ALTER WAREHOUSE COMPUTE_WH Suspend;

再次运行与我们之前相同的查询 -

USE SCHEMA SNOWFLAKE_SAMPLE_DATA.TPCH_SF100;
SELECT l_returnflag, l_linestatus,
SUM(l_quantity) AS sum_qty,
SUM(l_extendedprice) AS sum_base_price,
SUM(l_extendedprice * (l_discount)) AS sum_disc_price,
SUM(l_extendedprice * (l_discount) * (1+l_tax)) AS sum_charge,
AVG(l_quantity) AS avg_qty,
AVG(l_extendedprice) AS avg_price,
AVG(l_discount) AS avg_disc,
COUNT(*) AS count_order
FROM lineitem
WHERE l_shipdate <= dateadd(day, 90, to_date('1998-12-01'))
GROUP BY l_returnflag, l_linestatus
ORDER BY l_returnflag, l_linestatus;

单击查询ID。它将显示查询 ID 的链接。然后单击前面示例(元数据缓存)中所示的链接。检查查询配置文件,它将显示如下所示 -

查询结果

它显示了查询结果的重用。这意味着在没有仓库查询的情况下,它可以成功运行,并且整个结果集已从查询结果缓存中获取。

数据缓存

数据缓存发生在存储层。它缓存来自查询的存储文件头和列数据。它存储所有查询的数据,但不完全是查询结果。它将这些数据存储到虚拟仓库的SS中。当类似的查询运行时,Snowflake 会尽可能地使用数据缓存。用户无法禁用数据缓存。数据缓存可用于同一虚拟仓库上运行的所有查询。这意味着数据缓存与元数据和查询结果缓存不同,没有虚拟仓库就无法工作。

当查询运行时,其标题和列数据存储在虚拟仓库的SSD上。虚拟仓库首先读取本地可用数据(虚拟仓库的SSD),然后从远程云存储(实际Snowflake的存储系统)读取剩余数据。当缓存存储空间已满时,数据会根据最少使用方式不断下降。

让我们运行一个查询来看看查询结果缓存如何工作以及用户如何验证。

登录 Snowflake 并转到工作表。通过运行以下查询恢复仓库 -

ALTER WAREHOUSE COMPUTE_WH Resume;

使用以下 SQL 禁用 Query_Result 缓存 -

ALTER SESSION SET USE_CACHED_RESULT = FALSE;

运行以下查询 -

SELECT l_returnflag, l_linestatus,
SUM(l_quantity) AS sum_qty,
SUM(l_extendedprice) AS sum_base_price,
SUM(l_extendedprice * (l_discount)) AS sum_disc_price, SUM(l_extendedprice *
(l_discount) * (1+l_tax))
AS sum_charge, AVG(l_quantity) AS avg_qty,
AVG(l_extendedprice) AS avg_price,
AVG(l_discount) AS avg_disc,
COUNT(*) as count_order
FROM lineitem
WHERE l_shipdate <= dateadd(day, 90, to_date('1998-12-01'))
GROUP BY l_returnflag, l_linestatus
ORDER BY l_returnflag, l_linestatus;

单击查询ID。它将显示查询 ID 的链接。然后单击前面示例(元数据缓存)中所示的链接。检查查询配置文件,它将显示如下所示 -

数据缓存

根据查询配置文件,扫描了 88.6% 的数据。如果您注意到右侧,本地磁盘 IO = 2%,而远程磁盘 IO = 80%。这意味着使用的数据缓存非常低或没有使用。现在,运行以下查询。WHERE 子句有一点不同 -

SELECT l_returnflag, l_linestatus,
SUM(l_quantity) AS sum_qty,
SUM(l_extendedprice) AS sum_base_price,
SUM(l_extendedprice * (l_discount)) AS sum_disc_price, SUM(l_extendedprice *
(l_discount) * (1+l_tax))
AS sum_charge,
AVG(l_quantity) AS avg_qty,
AVG(l_extendedprice) AS avg_price,
AVG(l_discount) AS avg_disc,
COUNT(*) as count_order
FROM lineitem
WHERE l_shipdate <= dateadd(day, 90, to_date('1998-12-01'))
and l_extendedprice <= 20000
GROUP BY l_returnflag, l_linestatus
ORDER BY l_returnflag, l_linestatus;

单击查询ID。它将显示查询 ID 的链接。然后单击前面示例(元数据缓存)中所示的链接。检查查询配置文件,它将显示如下所示 -

点击查询ID

根据查询配置文件,扫描了 58.9% 的数据,远低于第一次。如果您注意到右侧,本地磁盘 IO 增加到 4%,而远程磁盘 IO = 0%。这意味着远程使用的数据非常少或没有。