テーブルを行の作成順序で除外する一般的な使用例があります。Spark Sql Dedup Rows
たとえば、ユーザーアクションのイベントログがあります。ユーザーは自分の好きなカテゴリを時折表示します。 分析段階では、ユーザーの最後にお気に入りのカテゴリのみを知りたいと考えています。
例データ:
id action_type value date
123 fav_category 1 2016-02-01
123 fav_category 4 2016-02-02
123 fav_category 8 2016-02-03
123 fav_category 2 2016-02-04
私たちは、日付列に応じてのみ、最新のアップデートを入手したいと思います。
select * from (
select *, row_number() over (
partition by id,action_type order by date desc) as rnum from tbl
)
where rnum=1;
しかし、その後、それは部分的マッパー側に集約されていないと我々は減速にシャッフルすべてのデータを取得します:私たちは、のコースSQLでそれを行うことができます。
私はこの問題SPARK-17662でのJiraを掲載しているし、それがより良いSQLスタイルの提案で閉じられました:
select id,
action_type,
max(struct(date, *)) last_record
from tbl
group by id,action_type
このソリューションは非常にきれいですが、まだ二つの問題があるさ:
- これをフィールドの1つがソート可能でない場合にはトリックは機能しません(マップ<>のように)
- フローの後半でフィールドの一部のみを選択すると、プッシュダウン述部が最適化されません私たちの流れは、最初から不必要なフィールドを無視します。
最終的に問題#1を解決しても問題#2に悩まされているこのためのUDAFを作成しました。
もっと良い解決策をお持ちの方はいらっしゃいますか?
もちろん、キーは注文可能でなければなりません - 私たちはそれらを最大限に活用しています。私のUDAFのポイントは、すべての値(非注文を含む)を保持することです。 述語のプッシュダウンについて、 'select id、action_type、max(struct(date、*))をt1からsとして実行していると仮定し、後でフローの中で' select id、 action_type、s.col2'である。プラン・オプティマイザは、他の列の生データを読み取ることさえできません。しかし、私たちは 'max(struct(date、*))'を持っているので、すべての列を読み込み(シャッフル)します。 – uzadude
Ah Ic、maxには値を順序付ける必要もあります。 –
2番目の問題は、ネストされたデータの列プルーニングです。私たちはSpark 2.2のためにこの分野でいくつかの仕事をするつもりです。既にhttps://github.com/apache/spark/pull/16043の作業があります。 –