【问题标题】:U-SQL Split a CSV file to multiple files based on Distinct values in fileU-SQL 根据文件中的不同值将 CSV 文件拆分为多个文件
【发布时间】:2017-04-05 09:39:31
【问题描述】:

我在 Azure Data Lake Store 中有数据,我正在使用带有 U-SQL 的 Azure 数据分析作业处理那里的数据。我有几个包含空间数据的 CSV 文件,类似于:

文件_20170301.csv

    longtitude| lattitude | date         | hour | value1
    ----------+-----------+--------------+------+-------
    45.121    | 21.123    | 2017-03-01   | 01   | 20
    45.121    | 21.123    | 2017-03-01   | 02   | 10
    45.121    | 21.123    | 2017-03-01   | 03   | 50
    48.121    | 35.123    | 2017-03-01   | 01   | 60
    48.121    | 35.123    | 2017-03-01   | 02   | 15
    48.121    | 35.123    | 2017-03-01   | 03   | 80

文件_20170302.csv

    longtitude| lattitude | date         | hour | value1
    ----------+-----------+--------------+------+-------
    45.121    | 21.123    | 2017-03-02   | 01   | 20
    45.121    | 21.123    | 2017-03-02   | 02   | 10
    45.121    | 21.123    | 2017-03-02   | 03   | 50
    48.121    | 35.123    | 2017-03-02   | 01   | 60
    48.121    | 35.123    | 2017-03-02   | 02   | 15
    48.121    | 35.123    | 2017-03-02   | 03   | 80

每个文件都包含不同日期和所有经纬度组合的数据。

我想合并我拥有的所有文件并拆分数据,这样我就可以为每个经纬度组合得到一个文件。

因此,在遍历文件夹中的所有文件并添加所有日期的所有数据后,我将得到以下结果:

文件_45_21.csv

    longtitude| lattitude | date         | hour | value1
    ----------+-----------+--------------+------+-------
    45.121    | 21.123    | 2017-03-01   | 01   | 20
    45.121    | 21.123    | 2017-03-01   | 02   | 10
    45.121    | 21.123    | 2017-03-01   | 03   | 50
    45.121    | 21.123    | 2017-03-02   | 01   | 20
    45.121    | 21.123    | 2017-03-02   | 02   | 10
    45.121    | 21.123    | 2017-03-02   | 03   | 50

文件_48_35.csv

    longtitude| lattitude | date         | hour | value1
    ----------+-----------+--------------+------+-------
    48.121    | 35.123    | 2017-03-01   | 01   | 60
    48.121    | 35.123    | 2017-03-01   | 02   | 15
    48.121    | 35.123    | 2017-03-01   | 03   | 80
    48.121    | 35.123    | 2017-03-02   | 01   | 60
    48.121    | 35.123    | 2017-03-02   | 02   | 15
    48.121    | 35.123    | 2017-03-02   | 03   | 80

理论上应该会发生以下情况:

  1. 在数据中查找经度和纬度组合的不同值
  2. 获取上述不同值的数组并为每个组合创建一个文件,并根据两个参数(经度和纬度)从源文件中提取数据

我正在努力的是如何开始循环和基于源中的两个参数提取数据,以及如何通过参数组合的不同值“分区”数据源。

【问题讨论】:

    标签: azure output azure-data-lake u-sql data-partitioning


    【解决方案1】:

    U-SQL 不直接支持动态 U-SQL,但可以使用“脚本编写脚本”技术来创建输出。然后,您可以手动运行此输出,或使用 Powershell 或 Azure 数据工厂之类的工具来运行它。

    我根据您的测试数据创建了一个简单的示例,部分基于来自here 的示例。

    // Get the initial fileset
    @input =
        EXTRACT longtitude float,
                lattitude float,
                date string,
                hour int,
                value1 int,
                filename string
        FROM "/input/File_201703{filename}"
        USING Extractors.Csv();
    
    
    // Add int version of the long and lat columns for grouping on
    @working =
        SELECT *,
               (int) longtitude AS int_long,
               (int) lattitude AS int_lat
        FROM @input;
    
    
    // Work out the filenames
    @filenames =
        SELECT String.Format("File {0}_{1}.csv", int_long, int_lat) AS outputFilename,
               int_long,
               int_lat
        FROM
        (
            SELECT int_long,
                   int_lat
            FROM @working
            GROUP BY int_long,
                     int_lat
        ) AS x;
    
    
    // Construct the dynamic usql and output it
    @output =
        SELECT x.xsort, "@input = EXTRACT longtitude float, lattitude float, date string, hour int, value1 int, filename string FROM \"input/File_201703{filename}\" USING Extractors.Csv();" AS usql
       FROM ( VALUES ( 10 ) ) AS x(xsort)
    
        UNION ALL
    
        SELECT x.xsort, "@working = SELECT *, (int) longtitude AS int_long, (int) lattitude AS int_lat FROM @input;" AS usql
        FROM ( VALUES ( 20 ) ) AS x(xsort)
    
        UNION ALL
    
        SELECT 30 AS xsort, String.Format("OUTPUT (SELECT * FROM @working WHERE int_long == {0} AND int_lat == {1}) TO \"/output/{2}\" USING Outputters.Csv();", int_long, int_lat, outputFilename) AS usql
        FROM @filenames;
    
    
    // Select only the usql column and sort the output
    @output =
        SELECT usql
        FROM @output
    ORDER BY xsort
    FETCH 100;
    
    
    OUTPUT @output
    TO "/output/dynamic.usql"
    USING Outputters.Text(delimiter : ' ', quoting : false);
    

    【讨论】:

    • 嗨@MichaelRys,您是否发现上述动态方法存在一些问题?它可以改进还是一个坏主意?感谢您收到任何反馈:)
    • 虽然我没有运行它,但它看起来还可以。出于性能原因,我可能已经合并了文件名创建和动态 U-SQL 创建。您基本上使用了我上面建议的使用 U-SQL 编写 U-SQL 方法。
    • 我只是想知道在数据库目录中获取数据,对其进行分区并将导出写入 csv 文件是否是个好主意。这会是一个可行的解决方案吗? USQL 仍然可以用于导入表中的数据并将数据导出到 csv。
    • 是的,你可以这样做。我的问题是增加了什么(例如,它是否提高了性能、维护或可扩展性等)?对我来说,当我可以证明 ADLA 表对我上面列出的项目有重要影响时,我会添加它们。如果您谈论的是普通的数据库表(例如 Azure SQL DB、Azure SQL 数据仓库),那么 ADLA 无法在本机上写入它们,因此您需要一些额外的步骤 - 您可以使用 Azure 数据工厂来安装一些东西来做这。我会权衡增加的复杂性与收益:)
    • @wBob:非常感谢!
    【解决方案2】:

    我建议查看文件集的概念以对许多文件进行操作(请参阅https://msdn.microsoft.com/en-us/library/azure/mt771650.aspx)以及一些基于值进行动态输出的建议,直到该功能可用为止(请参阅How do I partition a large file into files/directories using only U-SQL and certain fields in the file? 作为示例)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 2022-01-12
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多