2017-12-28 13 views
3

データファクトリでジョブのスケジュール設定に問題があります。 私は時間ごとにスケジュールされたジョブにアプローチしようとしています。毎時同じスクリプトを異なる条件で実行します。仮想ファイルセットの列と行セットの変数U-SQL

私はAzure Data Lake Storeに広がったAvroファイルの束を次のパターンで持っています。/Data/SomeEntity/{date:yyyy}/{date:dd}/SomeEntity_ {date:yyyy} {date:MM} {date:dd} __ {date:H}

1時間ごとに新しいファイルがData Lake Storeに追加されます。 ファイルを一度だけ処理するために、U-SQL仮想ファイルセットの列とData Lake Storeで作成したSyncTableの助けを借りて処理することにしました。

私のクエリは次のようになります。

DECLARE @file_set_path string = /Data/SomeEntity/{date:yyyy}/{date:MM}/{date:dd}/SomeEntity_{date:yyyy}_{date:MM}_{date:dd}__{date:H}; 
@result = EXTRACT [Id] long, 
.... 
date DateTime 
FROM @file_set_path 
USING someextractor; 

@rdate = 
    SELECT MAX(ProcessedDate) AS ProcessedDate 
    FROM dbo.SyncTable 
    WHERE EntityName== "SomeEntity"; 

@finalResult = SELECT [Id],... FROM @result 
CROSS JOIN @rdate AS r 
WHERE date >= r.ProcessedDate; 

私は句、私はクロスセットで焦がす行に参加するよどこに行セット変数を使用することはできませんので、しかし、この場合においてもU-SQLが正しいファイルを見つけることができませんし、常に設定されているすべてのファイルを返します。

回避策やその他の方法はありますか?

+0

"WHERE date ** == ** r.ProcessedDate;"にする必要がありますか? –

+0

最後に処理された日付の後にすべてのファイルを処理しようとしているので、いいえ – taffarel

答えて

0

また、ファイル・セットが動的にパーティションの除去を行うことができないことに注意してくださいは、参加します。

シンクポイントをADFから処理スクリプトに渡すことをお勧めします。その値はオプティマイザに認識され、ファイルセットのパーティション削除が実行されます。最悪の場合、前のスクリプトの同期テーブルからその値を読み取り、それを次のパラメータのパラメータとして使用する必要があります。

3

私はこのアプローチがうまくいかない、つまりdbo.SyncTableテーブルのデータ型を確認できるかどうかが分からない限りうまくいくと思いますか? @rdateをダンプし、そこに到達する値が期待どおりであることを確認してください。

私は期待通りに機能した簡単なデモをまとめました。

@working = 
    SELECT * 
    FROM (
     VALUES 
      ((int)1, DateTime.Parse("2017/12/31")), 
      ((int)2, DateTime.Parse("2018/01/01")), 
      ((int)3, DateTime.Parse("2018/02/01")) 
    ) AS x (id, someDate); 


@rdate = 
    SELECT MAX(ProcessedDate) AS maxDate 
    FROM dbo.SyncTable; 

//@output = 
// SELECT * 
// FROM @rdate; 

@output = 
    SELECT *, (w.someDate - r.maxDate).ToString() AS diff 
    FROM @working AS w 
     CROSS JOIN 
      @rdate AS r 
    WHERE w.someDate >= r.maxDate; 


OUTPUT @output TO "/output/output.csv" 
USING Outputters.Csv(); 

私はファイルパス(フルスクリプトhere)でこれを試してみました:SyncTableの私のコピーは、2018年1月1日の値を持つ一つのレコードを持っていました。覚えておくべきことはカスタムの日付形式です。Hは時間を0〜23の数字で表します。挿入時にSyncTableの日付に時刻コンポーネントがない場合は、デフォルトの真夜中(0)になります。つまり、全体日が収集されます。あなたのファイル構造は、あなたのパターンに応じて次のようになります。

"D:\Data Lake\USQLDataRoot\Data\SomeEntity\2017\12\31\SomeEntity_2017_12_31__8\test.csv"

は、私はあなたのファイルパスは、単一の第2セクションのアンダースコアと0と23の間になります時間のセクションの前に二重のアンダースコアを(持って注意してください10時までの数字)。あなたのファイルセットパスにファイルタイプや引用符がないことがわかりました。私はテストでtest.csvを使用しました。私の結果:多分あなたのファイル構造、あなたのSyncTableの値、データ型などにあなたが上に行く必要があり、

Results

は基本的に私はアプローチがうまくいくと思いますが、非常に適切ではない何かがあります問題が見つかるまで、中間の値をチェックアウトしてチェックします。

+0

仮想ファイルセットの列でチェックしましたか、ディレクトリパターンは何ですか? – taffarel

+0

パターンが1か月以上前のファイルの例として、他のファイルがありますか? あなたのクエリでそれらを除外できますか? btwパターンの最後の部分はファイル名ではなく、ファイルには拡張子が含まれていませんが、とにかく影響はないと思います – taffarel

1

wBobの完全なスクリプトの要点はあなたの問題を解決していませんか?ここでは、あなたが提起した問題のいくつかに対処するためのwBobの完全なスクリプトの非常にわずかに編集されたバージョンです:1)SyncTableでフィルタリングする能力、2)パターンの最後の部分はフォルダではなくファイル名です。サンプルファイルと構造:値は、準備段階でオプティマイザに知られていないので、\Data\SomeEntity\2018\01\01\SomeEntity_2018_01_01__1

DECLARE @file_set_path string = @"/Data/SomeEntity/{date:yyyy}/{date:MM}/{date:dd}/SomeEntity_{date:yyyy}_{date:MM}_{date:dd}__{date:H}"; 

@input = 
EXTRACT [Id] long, 
     date DateTime 
FROM @file_set_path 
USING Extractors.Text(); 

// in lieu of creating actual table 
@syncTable = 
SELECT * FROM 
    (VALUES 
    ("SomeEntity",  new DateTime(2018,01,01,01,00,00)), 
    ("AnotherEntity", new DateTime(2018,01,01,01,00,00)), 
    ("SomeEntity",  new DateTime(2018,01,01,00,00,00)), 
    ("AnotherEntity", new DateTime(2018,01,01,00,00,00)), 
    ("SomeEntity",  new DateTime(2017,12,31,23,00,00)), 
    ("AnotherEntity", new DateTime(2017,12,31,23,00,00)) 
    ) AS x (EntityName, ProcessedDate); 

@rdate = 
SELECT MAX(ProcessedDate) AS maxDate 
FROM @syncTable 
WHERE EntityName== "SomeEntity"; 

@output = 
SELECT *, 
     date.ToString() AS dateString 
FROM @input AS i 
    CROSS JOIN 
     @rdate AS r 
WHERE i.date >= r.maxDate; 


OUTPUT @output 
TO "/output/output.txt" 
ORDER BY Id 
USING Outputters.Text(quoting:false);