该代码在 2000 个小文件 (~10-50 Kb) ~ 1 分钟内执行速度非常快。并行度 = 5。

@arenaData =
    EXTRACT col1, col2, col3
    FROM @in
    USING Extractors.Tsv(quoting : true, skipFirstNRows : 1, nullEscape : "\\N", encoding:Encoding.UTF8);

@res =
    SELECT col1, col2, col3
    FROM @arenaData;
    OUTPUT @res
    TO @out
    USING Outputters.Csv();

但是,如果我像这样更改代码,则需要大约 1 小时
@arenaData =
    EXTRACT col1, col2, col3
    FROM @in
    USING Extractors.Tsv(quoting : true, skipFirstNRows : 1, nullEscape : "\\N", encoding:Encoding.UTF8);

@res =
    SELECT
         col1.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) AS col1_converted,
, col2, col3

    FROM @arenaData;
    OUTPUT @res
    TO @out
    USING Outputters.Csv();

为什么.NET 调用这么慢?我需要将源 CSV 文件中的日期格式转换为“yyyy-MM-dd HH:mm:ss”?我怎样才能有效地做到这一点?

最佳答案

很高兴听到您现在获得更好的表现!

您的作业使用在托管代码中执行的表达式在 2800 多个非常小的文件上运行,而不是像 U-SQL 中的一些更常见的 C# 表达式那样转换为 C++。

这会导致以下问题:

  • 您以一定数量的 AU 开始您的工作。然后每个 AU 启动一个 YARN 容器来执行您的部分工作。这意味着容器需要干净地初始化,这需要一些时间(您可以在 Vertex Execution View 中看到它作为创建时间)。现在这需要一些时间,如果您的顶点进行了大量处理,那么这并不是太多的开销。不幸的是,在您的情况下,小文件的处理速度非常快,因此开销很大。
  • 如果顶点只执行系统生成的代码,我们将其编码为 C++ 代码,那么我们可以重用容器而无需重新初始化时间。不幸的是,由于遗留了潜在的工件,我们无法重用在托管运行时执行的通用用户代码。所以在这种情况下,我们需要重新初始化容器,这需要时间(超过 2800 次)。

  • 现在根据您的反馈,我们正在改进我们的重新初始化逻辑(如果您对内联 C# 表达式不做任何花哨的事情,我们仍然可以重新初始化)。此外,一旦我们可以在单个顶点内处理多个小文件而不是每个顶点一个文件,它就会变得更好。

    您的解决方法是增加文件的大小,并可能避免自定义代码(当然并非总是可行)位于过多的顶点中。

    关于azure-data-lake - u-sql 作业非常慢,当我添加 .NET 调用时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42369787/

    10-13 05:18