使用 Azure Data Lake U-SQL SDK 运行和测试 U-SQL

重要

Azure Data Lake Analytics 于 2024 年 2 月 29 日停用。 了解更多信息,请查看此公告

对于数据分析,你的组织可以使用 Azure Synapse AnalyticsMicrosoft Fabric

开发 U-SQL 脚本时,通常会在本地运行和测试 U-SQL 脚本,然后再将其提交到云。 Azure Data Lake 为此方案提供了一个名为 Azure Data Lake U-SQL SDK 的 NuGet 包,通过此包可以轻松缩放 U-SQL 运行和测试。 还可以将此 U-SQL 测试与 CI(持续集成)系统集成,以自动执行编译和测试。

如果担心如何使用 GUI 工具手动运行和调试 U-SQL 脚本,则可以为此使用适用于 Visual Studio 的 Azure Data Lake 工具。 可以从 此处了解详细信息。

安装 Azure Data Lake U-SQL SDK

可以在 Nuget.org 上获取 Azure Data Lake U-SQL SDK。在使用它之前,需要确保具有如下所示的依赖项。

依赖

Data Lake U-SQL SDK 需要以下依赖项:

  • Microsoft .NET Framework 4.6 或更高版本

  • Microsoft Visual C++ 14 和 Windows SDK 10.0.10240.0 或更高版本(本文中称为 CppSDK)。 可通过两种方法获取 CppSDK:

    • 安装 Visual Studio Community Edition。 Program Files 文件夹下有一个 \Windows Kits\10 文件夹,例如 C:\Program Files (x86)\Windows Kits\10。 你还将在 \Windows Kits\10\Lib 下找到 Windows 10 SDK 版本。 如果未看到这些文件夹,请重新安装 Visual Studio,并确保在安装过程中选择 Windows 10 SDK。 如果已安装 Visual Studio,U-SQL 本地编译器将自动找到它。

      用于 Visual Studio 的 Data Lake 工具本地运行 Windows 10 SDK

    • 安装 用于 Visual Studio 的 Data Lake 工具。 可以在 中找到预打包的 Visual C++ 和 Windows SDK 文件 C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\ADL Tools\X.X.XXXX.X\CppSDK.

      在这种情况下,U-SQL 本地编译器无法自动找到依赖项。 需要为其指定 CppSDK 路径。 可以将文件复制到其他位置,也可以按原样使用它。

了解基本概念

数据根

数据根文件夹是本地计算帐户的“本地存储”。 它相当于 Azure Data Lake Analytics 帐户中的 Azure Data Lake Store 帐户。 切换到其他数据根文件夹就像切换到其他存储帐户一样。 如果要访问具有不同数据根文件夹的常用共享数据,则必须在脚本中使用绝对路径。 或者,在数据根文件夹下创建文件系统符号链接(例如,NTFS 上的 mklink ),以指向共享数据。

数据根文件夹用于:

  • 存储本地元数据,包括数据库、表、表值函数(TVF)和程序集。
  • 查找在 U-SQL 中定义为相对路径的输入和输出路径。 使用相对路径可以更轻松地将 U-SQL 项目部署到 Azure。

U-SQL 中的文件路径

可以在 U-SQL 脚本中使用相对路径和本地绝对路径。 相对路径相对于指定的数据根文件夹路径。 建议使用“/”作为路径分隔符,使脚本与服务器端兼容。 下面是相对路径及其等效绝对路径的一些示例。 在这些示例中,C:\LocalRunDataRoot 是数据根文件夹。

相对路径 绝对路径
/abc/def/input.csv C:\LocalRunDataRoot\abc\def\input.csv
abc/def/input.csv C:\LocalRunDataRoot\abc\def\input.csv
D:/abc/def/input.csv D:\abc\def\input.csv

工作目录

在本地运行 U-SQL 脚本时,在当前正在运行的目录下编译期间会创建工作目录。 除了编译输出之外,本地执行的所需运行时文件也将卷影复制到此工作目录。 工作目录根文件夹称为“ScopeWorkDir”,工作目录下的文件如下所示:

目录/文件 目录/文件 目录/文件 定义 DESCRIPTION
C6A101DDCB470506 运行时版本的哈希字符串 本地执行所需的运行时文件的卷影副本
Script_66AE4909AA0ED06C 脚本名称 + 脚本路径的哈希字符串 编译输出和执行步骤日志记录
_script_.abr 编译器输出 代数文件
_ScopeCodeGen_.* 编译器输出 生成的托管代码
_ScopeCodeGenEngine_.* 编译器输出 生成的本机代码
引用的程序集 程序集引用 引用的程序集文件
已部署资源 资源部署 资源部署文件
xxxxxxxx.xxx[1..n]_*.* 执行日志 执行步骤日志

从命令行使用 SDK

帮助程序应用程序的命令行接口

SDK 目录\build\runtime, LocalRunHelper.exe 是命令行助手程序,它为大多数常用的本地运行功能提供接口。 命令和参数开关都区分大小写。 若要调用它,请执行以下命令:

LocalRunHelper.exe <command> <Required-Command-Arguments> [Optional-Command-Arguments]

在不带参数或带help开关的情况下运行LocalRunHelper.exe,以显示帮助信息:

> LocalRunHelper.exe help
    Command 'help' :  Show usage information
    Command 'compile' :  Compile the script
    Required Arguments :
        -Script param
                Script File Path
    Optional Arguments :
        -Shallow [default value 'False']
                Shallow compile

在帮助信息中:

  • 命令 提供命令的名称。
  • 必需参数 列出必须提供的参数。
  • 可选参数 列出了具有默认值的可选参数。 可选布尔参数不需要额外的参数,其出现表示其默认值取反。

返回值和日志记录

帮助程序应用程序返回 0 ,如果失败,则 返回 -1 。 默认情况下,帮助程序将所有消息发送到当前控制台。 但是,大多数命令都支持 -MessageOut path_to_log_file 将输出重定向到日志文件的可选参数。

环境变量配置

U-SQL 本地运行需要指定一个数据根目录作为本地存储帐户,并指定一个 CppSDK 路径来满足依赖项需求。 可以在命令行中设置参数,也可以为它们设置环境变量。

  • 设置 SCOPE_CPP_SDK 环境变量。

    如果通过安装用于 Visual Studio 的 Data Lake 工具来Microsoft Visual C++ 和 Windows SDK,请验证是否具有以下文件夹:

    C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\Microsoft Azure Data Lake Tools for Visual Studio 2015\X.X.XXXX.X\CppSDK

    定义名为 SCOPE_CPP_SDK 的新环境变量以指向此目录。 或者将文件夹复制到其他位置,并指定 SCOPE_CPP_SDK

    除了设置环境变量之外,还可以在使用命令行时指定 -CppSDK 参数。 此参数覆盖默认的 CppSDK 环境变量。

  • 设置 LOCALRUN_DATAROOT 环境变量。

    定义一个名为 LOCALRUN_DATAROOT 的新环境变量,该变量指向数据根。

    除了设置环境变量之外,还可以在使用命令行时使用数据根路径指定 -DataRoot 参数。 此参数覆盖默认数据根环境变量。 需要将此参数添加到正在运行的每个命令行,以便覆盖所有作的默认数据根环境变量。

SDK 命令行用法示例

编译和运行

运行命令用于编译脚本,然后执行已编译的结果。 其命令行参数是编译和执行中的参数的组合。

LocalRunHelper run -Script path_to_usql_script.usql [optional_arguments]

下面是用于 运行的可选参数:

论点 默认值 DESCRIPTION
-CodeBehind 脚本.cs代码隐藏
-CppSDK CppSDK 目录
-DataRoot DataRoot 环境变量 用于本地运行的 DataRoot,默认为“LOCALRUN_DATAROOT”环境变量
-消息输出 将主机上的消息转储到文件
-平行 1 使用指定的并行度运行计划
-引用 后面代码的额外引用程序集或数据文件的路径列表,用“;”分隔
-UdoRedirect 生成 Udo 程序集重定向配置
-UseDatabase 大师 用于临时程序集注册背后的代码的数据库
-Verbose 显示运行时的详细输出
-WorkDir 当前目录 编译器使用情况和输出的目录
-RunScopeCEP 0 要使用的 ScopeCEP 模式
-ScopeCEPTempPath 临时 用于流数据的临时路径
-OptFlags 优化器标志的逗号分隔列表

下面是一个示例:

LocalRunHelper run -Script d:\test\test1.usql -WorkDir d:\test\bin -CodeBehind -References "d:\asm\ref1.dll;d:\asm\ref2.dll" -UseDatabase testDB –Parallel 5 -Verbose

除了合并编译和执行之外,还可以单独编译和执行已编译的可执行文件。

编译 U-SQL 脚本

编译命令用于将 U-SQL 脚本编译为可执行文件。

LocalRunHelper compile -Script path_to_usql_script.usql [optional_arguments]

下面是用于 编译的可选参数:

论点 DESCRIPTION
-CodeBehind [默认值‘False’] 脚本有.cs代码作为后端支持
-CppSDK [默认值 ''] CppSDK 目录
-DataRoot [默认值“DataRoot 环境变量”] 用于本地运行的 DataRoot,默认为“LOCALRUN_DATAROOT”环境变量
-MessageOut [默认值''] 将主机上的消息转储到文件
-参考文献 [默认值 ''] 后面代码的额外引用程序集或数据文件的路径列表,用“;”分隔
-Shallow [默认值“False”] 浅层编译
-UdoRedirect [默认值'False'] 生成 Udo 程序集重定向配置文件
-UseDatabase [默认值'master'] 用于临时程序集注册背后的代码的数据库
-WorkDir [默认值“Current Directory”] 编译器使用情况和输出的目录
-RunScopeCEP [默认值“0”] 要使用的 ScopeCEP 模式
-ScopeCEPTempPath [默认值'temp'] 用于流数据的临时路径
-OptFlags [默认值 ''] 优化器标志的逗号分隔列表

下面是一些用法示例。

编译 U-SQL 脚本:

LocalRunHelper compile -Script d:\test\test1.usql

编译 U-SQL 脚本并设置数据根文件夹。 这将覆盖设置的环境变量。

LocalRunHelper compile -Script d:\test\test1.usql –DataRoot c:\DataRoot

编译 U-SQL 脚本并设置工作目录、引用程序集和数据库:

LocalRunHelper compile -Script d:\test\test1.usql -WorkDir d:\test\bin -References "d:\asm\ref1.dll;d:\asm\ref2.dll" -UseDatabase testDB

执行编译的结果

execute 命令用于执行已编译的结果。

LocalRunHelper execute -Algebra path_to_compiled_algebra_file [optional_arguments]

下面是 execute 命令的可选参数:

论点 默认值 DESCRIPTION
-DataRoot '' 元数据执行的数据根。 它默认为 LOCALRUN_DATAROOT 环境变量。
-MessageOut '' 将主机上的消息转储到文件。
-平行 '1' 指示符,用于运行具有指定并行度级别的生成的本地运行步骤。
-Verbose 错误 用于显示运行时的详细输出的指示器。

下面是用法示例:

LocalRunHelper execute -Algebra d:\test\workdir\C6A101DDCB470506\Script_66AE4909AA0ED06C\__script__.abr –DataRoot c:\DataRoot –Parallel 5

将 SDK 与编程接口配合使用

编程接口都位于 LocalRunHelper.exe中。 可以使用它们来集成 U-SQL SDK 和 C# 测试框架的功能,以缩放 U-SQL 脚本本地测试。 在本文中,我将使用标准 C# 单元测试项目来演示如何使用这些接口测试 U-SQL 脚本。

步骤 1:创建 C# 单元测试项目和配置

  • 通过 文件 > 新建 > 项目 > Visual C# > 测试 > 单元测试项目 创建一个 C# 单元测试项目。

  • 添加 LocalRunHelper.exe 作为项目的引用。 LocalRunHelper.exe 位于 NuGet 包中的 \build\runtime\LocalRunHelper.exe。

    Azure Data Lake U-SQL SDK 添加参考

  • U-SQL SDK 支持 x64 环境,请确保将生成平台目标设置为 x64。 可以通过项目属性中的>生成>的"平台目标"来进行设置。

    Azure Data Lake U-SQL SDK 配置 x64 项目

  • 请确保将测试环境设置为 x64。 在 Visual Studio 中,可以通过测试 > 测试设置 > 默认处理器体系结构 > x64 设置它。

    Azure Data Lake U-SQL SDK 配置 x64 测试环境

  • 请确保将 NugetPackage\build 下的所有依赖项文件\runtime\ 复制到 ProjectFolder\bin\x64\Debug 下的项目工作目录。

步骤 2:创建 U-SQL 脚本测试用例

下面是 U-SQL 脚本测试的示例代码。 若要进行测试,需要准备脚本、输入文件和预期的输出文件。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using Microsoft.Analytics.LocalRun;
namespace UnitTestProject1
{
    [TestClass]
    public class USQLUnitTest
    {
        [TestMethod]
        public void TestUSQLScript()
        {
            //Specify the local run message output path
            StreamWriter MessageOutput = new StreamWriter("../../../log.txt");
            LocalRunHelper localrun = new LocalRunHelper(MessageOutput);
            //Configure the DateRoot path, Script Path and CPPSDK path
            localrun.DataRoot = "../../../";
            localrun.ScriptPath = "../../../Script/Script.usql";
            localrun.CppSdkDir = "../../../CppSDK";
            //Run U-SQL script
            localrun.DoRun();
            //Script output
            string Result = Path.Combine(localrun.DataRoot, "Output/result.csv");
            //Expected script output
            string ExpectedResult = "../../../ExpectedOutput/result.csv";
            Test.Helpers.FileAssert.AreEqual(Result, ExpectedResult);
            //Don't forget to close MessageOutput to get logs into file
            MessageOutput.Close();
        }
    }
}
namespace Test.Helpers
{
    public static class FileAssert
    {
        static string GetFileHash(string filename)
        {
            Assert.IsTrue(File.Exists(filename));
            using (var hash = new SHA1Managed())
            {
                var clearBytes = File.ReadAllBytes(filename);
                var hashedBytes = hash.ComputeHash(clearBytes);
                return ConvertBytesToHex(hashedBytes);
            }
        }
        static string ConvertBytesToHex(byte[] bytes)
        {
            var sb = new StringBuilder();
            for (var i = 0; i < bytes.Length; i++)
            {
                sb.Append(bytes[i].ToString("x"));
            }
            return sb.ToString();
        }
        public static void AreEqual(string filename1, string filename2)
        {
            string hash1 = GetFileHash(filename1);
            string hash2 = GetFileHash(filename2);
            Assert.AreEqual(hash1, hash2);
        }
    }
}

LocalRunHelper.exe 中的编程接口

LocalRunHelper.exe 为 U-SQL 本地编译、运行等提供编程接口。接口如下所示。

构造函数

public LocalRunHelper([System.IO.TextWriter messageOutput = null])

参数 类型 DESCRIPTION
消息输出 System.IO.TextWriter 对于输出消息,设置为 null 以使用控制台

性能

财产 类型 DESCRIPTION
AlgebraPath 字符串 代数文件的路径(代数文件是编译结果之一)
CodeBehindReferences 字符串 如果脚本具有其他代码隐藏引用,请指定用“;”分隔的路径
CppSdkDir 字符串 CppSDK 目录
CurrentDir 字符串 当前目录
DataRoot 字符串 数据根路径
DebuggerMailPath 字符串 调试器邮件槽的路径
生成Udo重定向 布尔 如果我们想生成程序集加载重定向覆盖配置
HasCodeBehind 布尔 如果脚本包含代码隐藏
InputDir 字符串 输入数据的目录
MessagePath 字符串 消息转储文件路径
OutputDir 字符串 输出数据的目录
并行度 整数 (int) 运行代数的并行度
ParentPid 整数 (int) 服务监控父进程的PID以便退出,设置为0或者负数则忽略。
ResultPath 字符串 结果导出文件路径
RuntimeDir 字符串 运行时目录
ScriptPath 字符串 在何处查找脚本
布尔 是否进行浅层编译
TempDir 字符串 临时目录
UseDataBase 字符串 指定用于临时程序集注册的代码所需数据库,默认情况下是 master。
WorkDir 字符串 首选工作目录

方法

方法 DESCRIPTION 返回 参数
public bool DoCompile() 编译 U-SQL 脚本 成功时返回 True
public bool DoExec() 执行编译的结果 成功时为 True
public bool DoRun() 运行 U-SQL 脚本(编译 + 执行) 成功时返回 True
public bool IsValidRuntimeDir(string path) 检查给定路径是否为有效的运行时路径 True(有效) 运行时目录的路径

常见问题

错误 1

E_CSC_SYSTEM_INTERNAL:内部错误! 无法加载文件或程序集“ScopeEngineManaged.dll”或其依赖项之一。 找不到指定的模块。

检查以下内容:

  • 请确保具有 x64 环境。 生成目标平台和测试环境应为 x64,请参阅 步骤 1:创建上述 C# 单元测试项目和配置
  • 请确保已将 NugetPackage\build 下的所有依赖项文件\r取消时间\复制到项目工作目录。

后续步骤