Snowflake - 缓存

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

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

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

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

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

元数据缓存

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

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

  • 表中的行数。

  • 列的最小/最大值

  • 列中的 DISTINCT 值的数量

  • 列中的 NULL 值的数量

  • 不同表版本的详细信息

  • 物理文件的引用

这些信息基本上由 SQL 优化器使用,以便更快地执行。可能有一些查询可以完全由元数据本身回答。对于此类查询,不需要虚拟仓库,但可能需要支付云服务费。

此类查询类似于 −

  • 所有 SHOW 命令

  • MIN、MAX,但仅限于 Integer/Number/Date 数据类型的列。

  • COUNT

让我们运行查询以查看元数据缓存的工作原理,用户可以验证。

登录 Snowflake 并转到 Worksheets。通过运行以下查询暂停仓库−

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 的链接。然后单击链接,如下所示 −

查询 ID

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

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

Profile

查询结果缓存

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

例如,如果用户 1 第一次运行查询,则结果将存储在缓存中。当用户 2 也尝试运行相同的查询时(假设基表和数据没有改变),它会从查询结果缓存中获取结果。

缓存的结果可用 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%。这意味着远程使用的数据非常少或没有使用。