如何减少和监控 Snowflake 中的计算资源?

Posted

技术标签:

【中文标题】如何减少和监控 Snowflake 中的计算资源?【英文标题】:How to reduce and monitor Compute resources in Snowflake? 【发布时间】:2021-05-18 13:09:23 【问题描述】:

我有几个与 Snowflake 的连接,它们发出 SQL 命令,包括我为手动调试/开发而运行的临时查询、我每天运行两次以制作汇总表的任务,以及 Chartio(一个仪表板应用程序)对我的汇总表运行间隔查询。

我最近使用了更多的积分,这主要是由于计算资源。我可以对不同仓库的不同连接进行分段,以隔离这些不同用户中的哪些用户获得的积分最多,但我希望直接使用 Snowflake 来关联谁在对应于最多积分的时间拨打了哪些电话。它不一定是完全自动化的方法,我可以做一些跑腿的工作,我只是不确定如何在不分割仓库的情况下做到这一点,这将需要一些工作和不确定性,因为它会影响生产。

我采取的应该有所帮助的明确步骤之一是减少为这些查询提供服务的仓库的大小。但我不确定如何更明确地细分和隔离造成最大成本的因素。

alter warehouse my_wh set warehouse_size=medium;

我在这里的文档中阅读了有关资源监视器的信息,但它对隔离方面没有多大帮助: https://docs.snowflake.com/en/user-guide/resource-monitors.html

最终最好的办法是让用户有一个资源监视器,这样我就可以确定来源,包括发出语句的表。

【问题讨论】:

【参考方案1】:

这更像是一个过程,而不是单个事件或一段代码,但这里有一个 SQL 查询可以提供帮助。要干净地隔离信用消耗,您需要单独的仓库。但是,可以估计用户随时间的信用消耗。这是一个估计值,因为仓库是一种共享资源,而且由于两个或多个用户可以同时使用一个仓库,所以我们能做的最好的事情就是找出一种方法来分配谁负责该消耗的哪一部分。

以下查询使用以下方法估算用户在一段时间内的信用消耗:

    仓库运行的每个时间段都会在 SNOWFLAKE.ACCOUNT_USAGE.METERING_HISTORY 视图中记录为一行。 如果在该段的持续时间内只有一个用户处于活动状态,则查询会将 100% 的使用量分配给该用户。 如果在一个段的持续时间内有多个用户处于活动状态,则查询将获取一个用户的总查询运行时间,然后将其除以该段中所有用户的总查询运行时间。这会按查询运行时按比例分配共享仓库。

#3 是近似值,但如果您不将其用于退款或向某人收取数据共享使用费用,则它是合适的。

请务必将仓库名称更改为您的 WH 名称,并为您要检查使用情况的持续时间设置开始和结束时间戳

with
TF(WH_NAME, START_DATE, END_DATE) as
(
    --     Warehouse    Start Date      End Date
    select 'TEST',      '2021-04-01',   '2021-05-01'  -- Replace values here
),
WH(START_TIME, END_TIME, CREDITS_USED) as
(
    select  START_TIME, END_TIME, CREDITS_USED
    from    "SNOWFLAKE"."ACCOUNT_USAGE"."METERING_HISTORY", TF
    where   "NAME"        = TF.WH_NAME    and
            "START_TIME" >= TF.START_DATE and
            "END_TIME"   <= TF.END_DATE
),
QRY(USER_NAME, START_TIME, END_TIME, DURATION) as
(
    select   USER_NAME,  START_TIME, END_TIME, TOTAL_ELAPSED_TIME
    from    "SNOWFLAKE"."ACCOUNT_USAGE"."QUERY_HISTORY", TF
    where   "WAREHOUSE_NAME" = TF.WH_NAME and
            "START_TIME" >= TF.START_DATE and
            "END_TIME"   <= TF.END_DATE
),
DUR(USER_NAME, WH_START_TIME, WH_END_TIME, DURATION) as
(
select   QRY.USER_NAME          as USER_NAME
        ,WH.START_TIME          as WH_START_TIME
        ,WH.END_TIME            as WH_END_TIME
        ,sum(QRY.DURATION)      as QRY_DURATION
from    WH
    left join QRY on
        QRY.START_TIME > WH.START_TIME and
        QRY.END_TIME   < WH.END_TIME
group by    WH_START_TIME, WH_END_TIME, USER_NAME
),
WHBU (WH_START_TIME, WH_END_TIME, CREDITS, DURATION, USER_NAME) as
(
select   WH.START_TIME           as WH_START_TIME
        ,WH.END_TIME             as WH_END_TIME
        ,WH.CREDITS_USED         as CREDITS
        ,DUR.DURATION            as DURATION
        ,DUR.USER_NAME           as USER_NAME
from    WH
    left join DUR on WH.START_TIME = DUR.WH_START_TIME and
                     WH.END_TIME   = DUR.WH_END_TIME
order by WH.START_TIME, USER_NAME
),
CBU(USER_NAME, CREDITS) as
(
select   USER_NAME
        ,CREDITS * DURATION / sum(DURATION) over (partition by WH_START_TIME, WH_END_TIME) as PRO_RATED_CREDITS
from    WHBU
)
select      USER_NAME
            ,sum(CREDITS) as ESTIMATED_CREDITS
from        CBU
group by    USER_NAME
order by    ESTIMATED_CREDITS desc
;

【讨论】:

谢谢,这让我看看估计谁用得最多。除了我在您提供的相同日期范围内得到非常大的答案,例如在 100k 数量级的学分中,昨天我使用了 ~20 个学分,前一天使用了 ~150 个学分。此查询的答案可能与所有用户的平均每日消费量相差甚远,这是有原因的吗?如果它正在做类似线性拟合的事情,那么最近应该没有发生任何事情让所有用户做出糟糕的预测。 这显然是错误的。它对我有用,但我可能需要在其他系统上对其进行测试,以确保它更普遍地工作。让我检查它为什么给出错误的答案并修复查询。 @MarkMcGown,请尝试更新后的查询。我隔离了 CTE 的一个虚假部分,并从另一个表表达式中简单地更改为“select *”。这个应该可以的。 太棒了,就每个用户的数量和信用使用而言,这很有效并且更有意义。我对您的解决方案的最后一个问题是,过去进行预测意味着什么?或者它只是过去的历史数据?无论哪种方式,您都可能建议您熟悉文档,以帮助我理解为什么这种信用方法有效。 这与其说是预测,不如说是估计。当两个或多个用户同时在同一个仓库上运行查询时,我们需要一种方法来估计按比例分配的使用量。查询持续时间只是一个估计值。可能有不正确的时候。例如,用户 1 可能在很长一段时间内运行大量快速查询以保持仓库处于活动状态,而用户 2 运行单个长时间运行的查询。可以说用户 1 对使用负有更多责任,因为这种活动模式使仓库暂停的时间比用户 2 的活动长。

以上是关于如何减少和监控 Snowflake 中的计算资源?的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 Snowflake 存储过程中的会话参数

AWS 架构最佳实践概述

在 Snowflake 中,仓库配置是如何发生的

从 Kubectl Top 说起, 谈谈 Kubernetes 是如何进行资源监控的?

新一代数据仓库:Snowflake 弹性数仓介绍

如何在 Snowflake sql 中使用 partition by 和 order by 计算不同的值?