分析 Snowpark Python 存储过程处理程序

您可以使用内置的代码分析器了解执行处理程序代码所消耗的时间或内存。分析器可以生成信息,用以描述执行每行过程处理程序代码所消耗的时间或内存。

使用分析器可以生成报告,每次专注于以下其中一个方面:

  • 每行代码的执行时间,报告中显示每行代码被执行的次数、执行所花费的时间等。

  • 每行代码的内存使用量,报告中显示每行代码消耗的内存量。

分析器会将生成的报告保存到您指定的 Snowflake 内部用户暂存区。您可以使用 StoredProcedureProfiler.get_output 系统函数 读取分析器的输出结果

备注

分析会对 Python 代码的执行引入额外的性能开销,并可能影响查询的性能。它用于开发和测试,不得在持续的生产工作负载中启用。

所需权限

在调用 StoredProcedureProfiler.set_active_profiler 函数后执行存储过程时,Snowflake 会检查执行该过程的用户的以下权限:

  • 您必须对分析输出暂存区具有读写权限。

  • 如果被分析的存储过程是 调用者权限存储过程,则您必须使用对该存储过程具有 USAGE 权限的角色。

  • 如果被分析的存储过程是 所有者权限存储过程,则您必须使用对该存储过程具有 OWNERSHIP 权限的角色。

限制

  • 仅支持存储过程。暂不支持 UDFs。

  • 不支持递归分析。仅分析指定模块的顶层函数,而不分析函数内部定义的函数。

  • 不支持对通过 snowflake.snowpark API 在客户端创建的存储过程进行分析。

  • 不分析通过 joblib 并行运行的 Python 函数。

  • 无法分析系统定义的存储过程。它们没有生成任何输出。

  • 分析 API 必须在调用过程的相同线程中使用。

用途

设置好要使用的分析器后,您只需简单地调用存储过程,即可生成分析器输出。在存储过程执行完成后,分析器的输出会写入到您指定的暂存区内的文件。您可以通过系统函数提取分析器输出,如下所述。

按照代码中的以下步骤设置和使用分析器:

  1. Session 对象获取分析器对象。

  2. 指定应将分析输出写入到的 Snowflake 暂存区。

  3. 启用分析器并设置配置文件报告应关注的内容。

  4. 调用存储过程。

  5. 查看分析输出。

获取分析器对象

在 Python 中,创建类型为 StoredProcedureProfiler 的变量,用于配置和运行分析器。

# Create your sesssion
session = Session.builder.configs(CONNECTION_PARAMETERS).create()

# Acquire profiler object
profiler = session.stored_procedure_profiler()
Copy

指定应将分析输出写入到的 Snowflake 暂存区

在运行分析器之前,您必须指定一个暂存区,用于保存输出。要指定暂存区,请调用 StoredProcedureProfiler.set_target_stage,指定报告应写入的内部 Snowflake 暂存区 的完全限定名称。

请记住以下几点:

  • 暂存区名称必须是完全限定的名称。

  • 如果您放入此函数的暂存区不存在,Snowflake 将创建具有该名称的临时暂存区。

  • 如果您要将分析器输出保留在会话范围之外,请在执行 set_target_stage 之前创建一个永久暂存区,并在函数调用中指定该永久暂存区的名称。

  • 如果您没有使用 set_target_stage 设置目标暂存区,Snowflake 会将当前会话的临时暂存区设置为目标暂存区。要发现该临时暂存区,请调用 Session.get_session_stage

以下示例代码会创建一个临时暂存区 profiler_output,用于接收分析器输出。

profiler.set_target_stage("mydb.myschema.profiler_output")
Copy

通过指定分析器的关注点来启用分析器

使用 StoredProcedureProfiler.set_active_profiler 函数,指定一个值,指明要生成哪种分析报告。

  • 要希望分析器报告专注于代码行使用活动,请将参数设置为 LINE 值(不区分大小写),如下所示:

    profiler.set_active_profiler("LINE")
    
    Copy
  • 要希望分析器报告专注于内存使用活动,请将参数设置为 MEMORY 值(不区分大小写),如下所示:

    profiler.set_active_profiler("MEMORY")
    
    Copy

要禁用分析器,请使用 StoredProcedureProfiler.disable 函数。

调用存储过程

启用分析器后,调用您的存储过程

session.call("my_stored_procedure")
Copy

查看分析输出

执行结束时,您可以使用 StoredProcedureProfiler.get_output 函数访问输出。

profiler.get_output()
Copy

添加用于分析的其他模块

分析时,您可以包含默认不包含的模块。

默认情况下,系统分析您的模块中定义的方法。这些方法包括以下内容:

  • 处理程序方法

  • 模块中定义的方法

  • 从包或其他模块导入的方法

要包含用于分析的其他模块,请使用 StoredProcedureProfiler.register_modules 函数,指定要包含的模块。

以下示例中的代码注册模块 module_A 和 module_B 以进行分析。

profiler.register_modules(["module_A", "module_B"])
Copy

要取消注册已注册的模块,请使用不带实参的 register_modules,如以下示例所示。

profiler.register_modules()
Copy

示例

以下示例展示了如何使用分析器生成并检索代码行使用情况的报告。

本示例中的代码创建过程 profiler_test_proc

CREATE OR REPLACE PROCEDURE profiler_test_proc()
RETURNS NUMBER
LANGUAGE PYTHON
RUNTIME_VERSION = 3.8
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'main'
AS
$$
from snowflake.snowpark.functions import col, udf

def main(session):
  df = session.sql("select 1")
  return df.collect()[0][0]
$$;
Copy

以下示例中的代码设置一个分析器,然后分析 profiler_test_proc 过程。

profiler = profiler_session.stored_procedure_profiler
profiler.register_modules(["profiler_test_proc"])
profiler.set_target_stage(
  f"{db_parameters['database']}.{db_parameters['schema']}.{tmp_stage_name}"
)

profiler.set_active_profiler("LINE")

profiler_session.call("profiler_test_proc")
res = profiler.get_output()
print(res)

profiler.disable()
profiler.register_modules([])
Copy

生成的代码行分析器输出如下所示:

Handler Name: main
Python Runtime Version: 3.8
Modules Profiled: ['main_module']
Timer Unit: 0.001 s

Total Time: 0.0619571 s
File: _udf_code.py
Function: main at line 4

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     4                                           def main(session):
     5         1          0.4      0.4      0.6      df = session.sql("select 1")
     6         1         61.6     61.6     99.4      return df.collect()[0][0]
语言: 中文