Snowflake 简明教程

Snowflake - Cache

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

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

  1. Metadata Caching

  2. Query Result Caching

  3. Data Caching

默认情况下,为所有雪花会话启用缓存。但用户可以根据自己的需要将其禁用。但是,用户只能禁用“查询结果”缓存,但不能禁用 Metadata CachingData Caching

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

Metadata Caching

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

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

  1. 表中的行数。

  2. 列的最小/最大值

  3. 列中的 DISTINCT 值数量

  4. 列中的 NULL 值数量

  5. 不同表版本的信息

  6. References of physical files

这些信息基本上由 SQL 优化器用于更快地执行。可能会有一些查询可以通过元数据本身完全得到解答。对于此类查询,无需虚拟仓库,但可能会适用云服务费用。

这类查询类似于:

  1. All SHOW commands

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

  3. COUNT

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

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

query id

默认情况下,它将打开提及 SQL 的详细信息页面。单击 Profile 选项卡。它将显示 100% 基于元数据的查询结果。这意味着无需任何计算仓库,就能根据元数据缓存运行并获取结果。

下图显示了上述步骤:

profile

Query Result Caching

查询结果由云服务层存储和管理。这在同一查询多次运行时非常有用,但前提条件是查询必须多次运行期间的基础数据或基础表保持不变。此缓存具有一个独特的特性,对同一个帐户内的其他用户可用。

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

缓存结果可保存 24 小时。但是,每次重新运行同一查询时,24 小时的计时器都会重置。例如,如果查询在上午 10 点运行,其缓存将持续到次日上午 10 点。如果同一查询在同一天下午 2 点重新运行,现在缓存将持续到次日下午 2 点。

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

  1. 应该重新运行完全相同的 SQL 查询。

  2. SQL 中不应该有任何随机函数。

  3. 用户必须有适当的权限才能使用它。

  4. 在运行查询时应用启用查询结果。默认情况下会启用,直至另行设置。

以下是一些使用查询结果缓存的情况 −

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

  2. 非常频繁运行的查询。

  3. Queries those are complex.

  4. 重构另一个查询的输出,如“使用表函数 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 的链接。然后单击链接,如上一个示例(Metadata-Caching)中所示。检查查询概要文件,它将如下所示 −

query profile

它显示已扫描 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;

单击 Query ID。它将显示查询 ID 的链接。然后单击链接,如上一个示例(Metadata-Caching)中所示。检查查询概要文件,它将如下所示 −

query result

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

Data Cache

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

当运行查询时,其标头和列数据存储在虚拟仓库的 SSD 上。虚拟仓库首先读取本地可用数据(虚拟仓库的 SSD),然后从远程云存储(Snowflake 的实际存储系统)读取剩余数据。当缓存存储空间填满时,数据会根据最近最少使用(LRU)原则进行丢弃。

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

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

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;

单击 Query ID。它将显示查询 ID 的链接。然后单击链接,如上一个示例(Metadata-Caching)中所示。检查查询概要文件,它将如下所示 −

data cache

根据查询概要文件,已扫描 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;

单击 Query ID。它将显示查询 ID 的链接。然后单击链接,如上一个示例(Metadata-Caching)中所示。检查查询概要文件,它将如下所示 −

click query id

根据查询概要文件,已扫描 58.9% 的数据,这比第一次低得多。如果你注意到右侧,则本地磁盘 IO 已增至 4%,而远程磁盘 IO = 0%。这意味着几乎没有使用或根本没有从远程使用数据。