更新时间:2026-10-16 GMT+08:00
分享

Vectorized UDF

Vectorized UDF是向量化执行的函数,是为解决传统行式UDF性能瓶颈而设计的高效函数。入参、出参通常为PyArrow或者Pandas类型。

示例

下文提供两个示例展示如何使用Vectorized UDF。

  • 示例一:使用PyArrow进行向量化加速。通过 `con.create_scalar_function` 显式注册PyArrow向量化UDF,框架会根据类型注解自动识别为PyArrow类型,再通过`ds.map`调用。
    import os
    import ibis
    import aura_frame as aura
    from aura_frame.multimodal import ai_lake
    from aura_frame.multimodal.types.vectorized import PyarrowVector
    import pyarrow.compute as pc
    
    target_database = "test"  #在LakeFormation中创建数据库,例如:test。具体操作,请参见创建LakeFormation实例并规划元数据
    #连接AuraJobV2端点,具体参数说明,请参见建立与AuraJobV2端点的连接。
    con = ai_lake.connect(
        aura_endpoint=os.getenv("aura_endpoint"),         # AuraJobV2端点所在的终端节点(Endpoint)
        aura_endpoint_id=os.getenv("aura_endpoint_id"),    # AuraJobV2端点ID
        aura_endpoint_name=os.getenv("aura_endpoint_name"),# AuraJobV2端点名称
        aura_workspace_id=os.getenv("aura_workspace_id"),  # 工作空间ID
        lf_catalog_name=os.getenv("lf_catalog_name"),      # LakeFormation Catalog名称
        access_key=os.getenv("access_key"),                # 访问密钥ID(AK)
        secret_key=os.getenv("secret_key"),                # 访问密钥(SK)
        default_database="postgres",                       # LakeFormation数据库名称
        use_single_cn_mode=True,   # 是否开启单CN模式
        logging_level=logging.INFO # 设置日志级别
    )
    #配置UDF部署工作区,具体参数说明,请参见配置UDF部署工作区。
    con.set_function_staging_workspace(
        obs_directory_base=os.getenv("obs_directory_base"),  # 并行文件系统中UDF的存储路径
        obs_bucket_name=os.getenv("obs_bucket_name"),       # 并行文件系统名称
        obs_server=os.getenv("obs_server"),                  # OBS终端节点(Endpoint)
        access_key=os.getenv("access_key"),                  # 访问密钥ID(AK)
        secret_key=os.getenv("secret_key"),                  # 访问密钥(SK)
    )
    def calculate_product_pyarrow(
        prices: PyarrowVector[float],
        quantities: PyarrowVector[int],
    ) -> PyarrowVector[float]:
        return PyarrowVector[float](pc.multiply(prices, quantities))
    
    try:
        # 创建测试表并写入数据
        table_name = "sales_records"
        table_schema = ibis.schema({"price": "float64", "quantity": "int32"})
        con.sql(f'DROP TABLE IF EXISTS "{target_database}"."{table_name}";')
        con.create_table(
            table_name,
            schema=table_schema,
            database=target_database,
            table_format="orc",
            if_not_exists=True,
        )
        con.sql(f'''
        INSERT INTO "{target_database}"."{table_name}" (price, quantity) VALUES
            (100.0, 10),
            (200.0, 20),
            (150.0, 15)
        ''')
        # 删除已存在的同名UDF(支持重复执行)
        con.delete_function("calculate_product_pyarrow", database=target_database, if_it_exists=True)
        # 显式注册 PyArrow 向量化 UDF
        udf_pyarrow = con.create_scalar_function(
            calculate_product_pyarrow,
            name="calculate_product_pyarrow",
            database=target_database,
            register_type=aura.udf.RegisterType.STAGED,
        )
        ds = con.load_dataset("sales_records", database=target_database)
        ds = ds.map(fn=udf_pyarrow, on=[ds.price, ds.quantity], as_col="product_column")
        ds = ds.select_columns(ds.price, ds.quantity, ds.product_column)
        print("PyArrow 向量化结果:")
        print(ds.execute())
    finally:
        con.close()
  • 示例二:使用Pandas进行向量化加速。通过`@aura.udf.pandas`装饰器隐式注册Pandas向量化UDF,注册类型为`STAGED`。
    import os
    import ibis
    import aura_frame as aura
    from aura_frame.multimodal import ai_lake
    from aura_frame.multimodal.types.vectorized import PandasVector
    import pandas as pd
    
    target_database = "test"
    # 隐式注册UDF
    @aura.udf.pandas(database=target_database, register_type=aura.udf.RegisterType.STAGED)
    def calculate_product_pandas(
        prices: PandasVector[float],
        quantities: PandasVector[int],
    ) -> PandasVector[float]:
        return PandasVector[float](prices * quantities, dtype=pd.Float64Dtype())
    con = ai_lake.connect(
        aura_endpoint=os.getenv("aura_endpoint"),         # AuraJobV2端点所在的终端节点(Endpoint)
        aura_endpoint_id=os.getenv("aura_endpoint_id"),    # AuraJobV2端点ID
        aura_endpoint_name=os.getenv("aura_endpoint_name"),# AuraJobV2端点名称
        aura_workspace_id=os.getenv("aura_workspace_id"),  # 工作空间ID
        lf_catalog_name=os.getenv("lf_catalog_name"),      # LakeFormation Catalog名称
        lf_instance_id=os.getenv("lf_instance_id"),        # LakeFormation实例ID
        project_id=os.getenv("project_id"),                # 项目ID
        access_key=os.getenv("access_key"),                # 访问密钥ID(AK)
        secret_key=os.getenv("secret_key"),                # 访问密钥(SK)
        default_database=target_database,                  # 默认数据库
        use_single_cn_mode=True,                           # 是否开启单CN模式
    )
    con.set_function_staging_workspace(
        obs_directory_base=os.getenv("obs_directory_base"),  # 并行文件系统中UDF的存储路径
        obs_bucket_name=os.getenv("obs_bucket_name"),        # 并行文件系统名称
        obs_server=os.getenv("obs_server"),                  # OBS终端节点(Endpoint)
        access_key=os.getenv("access_key"),                  # 访问密钥ID(AK)
        secret_key=os.getenv("secret_key"),                  # 访问密钥(SK)
    )
    try:
        # 创建测试表并写入数据
        table_name = "sales_records"
        table_schema = ibis.schema({"price": "float64", "quantity": "int32"})
        con.sql(f'DROP TABLE IF EXISTS "{target_database}"."{table_name}";')
        con.create_table(
            table_name,
            schema=table_schema,
            database=target_database,
            table_format="orc",
            if_not_exists=True,
        )
        con.sql(f'''
        INSERT INTO "{target_database}"."{table_name}" (price, quantity) VALUES
            (100.0, 10),
            (200.0, 20),
            (150.0, 15)
        ''')
        # 删除已存在的同名UDF(支持重复执行)
        con.delete_function("calculate_product_pandas", database=target_database, if_it_exists=True)
        # 使用 Pandas 向量化 UDF(已在上方通过装饰器隐式注册)
        ds2 = con.load_dataset("sales_records", database=target_database)
        ds2 = ds2.map(fn=calculate_product_pandas, on=[ds2.price, ds2.quantity], as_col="product_column")
        ds2 = ds2.select_columns(ds2.price, ds2.quantity, ds2.product_column)
        print("Pandas 向量化结果:")
        print(ds2.execute())
    finally:
        con.close()

相关文档