web-dev-qa-db-ja.com

Azure SQL Warehouse-データの取り込み-巨大な固定幅(カンマ付き)ファイルを区切り文字に変換します

この質問を正しく構成しているかどうかさえわかりませんが、試してみます。LinuxシステムでOracleエクスポートから生成された大量のテキストファイルがたくさんあります。各ファイルのサイズは約30 GBで、そのうちの約50個があります。

目標は、このデータをAzure SQL Data Warehouseにエクスポートすることです。この場合のBCPは、データのサイズを考慮して適切な方法ではないため、Polybaseを使用する必要がありました。

ASCIIからUTF8エンコーディングに変換した後、外部テーブルのクエリ中に問題が発生しました。Polybaseは、各行に改行がある固定幅のテキストファイルでうまく再生できません。

テキストファイルは次のようになります。

 101,102,103,104,105,106,107 
 108,108,109,110,111,112,113 
 114,115,116,117,118,119,120 
 121,122,123 
 
-何もない、空白行
 .. ____。] 201,202,203,204,205,206,207 
 208,209,210,211,212,213,214 
 215,216,217 

Polybaseは101から107までの処理を試み、このファイルに処理するのに十分な列がなかったというエラーメッセージが表示されます。

これが私の考えていることです。固定幅と改行は、改行を行区切り文字として扱います。

このファイルを次のように変換するにはどうすればよいですか。

 101、102、103、104、105、106、107、108、108、109、110、111、112、113、114、115、116、117、118、119、120、121、122、123

編集: これはサンプルデータです ファイルから。私はそれをWindows VMのgit bashで開きました。

これらのファイルには、,を列セパレータとして使用します。問題は、各行が複数の行を生成するため、Polybase外部テーブルからそれらを処理することが難しいことです。

5
RK Kuppala

最終的にsedを使用してファイルをクレンジングしました

zcat myfile.txt.gz | sed -r 's/[ ]+/vin/g'|tr -d '\n'|tr 'vinvin' '\n'|grep -v '^$' > myfile.txt

これにより、ソースファイルのフォーマットの問題が解決されました。これらのファイルがAzure Blob Storageにアップロードされると、残りは簡単でした。 Polybaseを介してBLOB上のファイルを指す外部テーブルを作成し、CREATE TABLE dbo.internal AS SELECT * FROM blob.externalを使用して内部テーブルを作成しました。 700 DWH容量のAzure DWHインスタンスは、外部テーブルから5分で約50 mln行をロードできました。

2
RK Kuppala

Polybaseは強力ですが、それほど洗練されていないため、この奇妙な形式を処理できません。私が見るように、3つのオプションがあります。

  1. ソースのファイル形式を修正してください。固定幅と区切りファイル形式の奇妙な組み合わせを使用する代わりに、.csvなどの標準ファイル形式を使用します。列区切り文字がキャリッジリターンまたはコンマのいずれかであるこの形式は、本当に奇妙だと思います。これを簡単に読み取ることができるツールはありますか?これはあなたが働いている一般的な形式ですか?
  2. 区切り文字の1つを指定するファイルを1つの行にインポートし、他の区切り文字に基づいて細断します。私はあなたのサンプルデータでこれを試し始めましたが、それほど遠くに行きませんでした。行ごとに実際に列数は異なりますか?サンプルデータでは、行1は24列、行2は17列です。 Gist を介して、データを正確に表す小さなサンプルファイルを提供してください。
  3. 高度にカスタマイズされたインポートルーチンを記述します。 csv、タブ区切り、パイプ区切り、XML、JSONなどの標準データ交換形式を使用するポイントは、データをインポートするたびに高度にカスタム化されたルーチンを記述する必要がないことです。ただし、ソースでファイルを変更したり、段階的にインポートしたりできない場合、これはオプションになる可能性があります。私は最近、Azure Data Lake Analytics(ADLA)とU-SQLを使用しており、可能性でこれを実行できます。

上記の質問に答えて、サンプルファイルを提供してください。私がお手伝いします。

6
wBob

16進エディタによると、サンプルファイルには、一部の行末に単一のラインフィード(0A)があり、行間の区切り文字として2つのラインフィードがあります。

hex view of sample file

U-SQLカスタムエクストラクターはこのファイルを処理できる可能性がありますが、30GBのフルファイルで問題が発生するかどうか疑問に思います。

指示

  1. Azure Data Lake Analytics (ADLA)アカウントをまだ持っていない場合は、セットアップします。
  2. Visual Studioで新しいU-SQLプロジェクトを作成します。 ADLAツール が必要になります。
  3. U-SQLスクリプトを追加し、以下のテキストをU-SQL分離コードファイルに追加します。

    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using Microsoft.Analytics.Interfaces;
    
    namespace Utilities
    {
    [SqlUserDefinedExtractor(AtomicFileProcessing = true)]
    public class MyExtractor : IExtractor
    {
        //Contains the row
        private readonly Encoding _encoding;
        private readonly byte[] _row_delim;
        private readonly char _col_delim;
    
        public MyExtractor()
        {
            _encoding = Encoding.UTF8;
            _row_delim = _encoding.GetBytes("\n\n");
            _col_delim = '|';
        }
    
        public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
        {
            string s = string.Empty;
            string x = string.Empty;
    
            foreach (var current in input.Split(_row_delim))
            {
                using (System.IO.StreamReader streamReader = new StreamReader(current, this._encoding))
                {
                    while ((s = streamReader.ReadLine()) != null)
                    {
                        //Strip any line feeds
                        //s = s.Replace("/n", "");
    
                         // Concatenate the lines
                        x += s;
                    }
    
                    //Create the output
                    output.Set<string>(0, x);
                    yield return output.AsReadOnly();
    
                    // Reset
                    x = string.Empty;
    
                }
            }
        }
    }
    }
    
  4. カスタムエクストラクターを使用してファイルを処理します。

    @input =
    EXTRACT col string
    FROM "/input/input42_2.txt"
    USING new Utilities.MyExtractor();
    
    
    // Output the file
    OUTPUT @input
    TO "/output/output.txt"
    USING Outputters.Tsv(quoting : false);
    

これにより、Polybaseを使用してインポートできるクリーンアップファイルが生成されました。

Polybase result

幸運を!

3
wBob