LoginSignup
4
0

More than 5 years have passed since last update.

Hive で「グループごとに1件だけ取得」する

Last updated at Posted at 2018-08-08

Hive で「グループごとに1件だけ取得」をやろうとしたときに、今まで ROW_NUMBER を使ってやっていたが、Hivemall の EACH_TOP_K を使うという方法もあると知ったのでメモ。

参考: Top N 件をとる効率的なHive / Prestoクエリ

今回は Treasure Data のサンプルデータセットにある NASDAQ の株価テーブルを使って「各銘柄の最新の株価を取得したい」とする。

ROW_NUMBER

普通に ROW_NUMBER を使って書くとこう。

SELECT time, symbol, volume
FROM (
  SELECT
    time, symbol, volume,
    ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY time DESC) AS rank
  FROM sample_datasets.nasdaq
) AS t
WHERE rank = 1

EACH_TOP_K

Hivemall の EACH_TOP_K 関数 を使うと、このように書ける。

SELECT EACH_TOP_K(
  1,                -- 上位 1 件のみを取得
  symbol,           -- symbol (銘柄) ごとに取得
  time,             -- time が大きい順に
  symbol, volume    -- 追加で出力するカラム
) AS (rank, time, symbol, volume)
FROM (
  SELECT time, symbol, volume
  FROM sample_datasets.nasdaq
  CLUSTER BY symbol  -- EACH_TOP_K に渡す前に CLUSTER BY でまとめておく必要がある
) AS t

パフォーマンス比較

ROW_NUMBER
Stage-Stage-1: Map: 1  Reduce: 1   Cumulative CPU: 115.69 sec
Total MapReduce CPU Time Spent: 1 minutes 55 seconds 690 msec

MapReduce time taken: 124.516 seconds
EACH_TOP_K
Stage-Stage-1: Map: 1  Reduce: 1   Cumulative CPU: 76.0 sec
Total MapReduce CPU Time Spent: 1 minutes 16 seconds 0 msec

MapReduce time taken: 85.171 seconds

EACH_TOP_K の方が約 1.46 倍速い。

NASDAQ のサンプルデータは約880万行だったが、約2億行ある別のデータで同様に比較した場合は EACH_TOP_K の方が約 1.1 倍速いという結果になった。

データによってはそれほど差が大きわけではないが、Hivemall が使える場合は EACH_TOP_K を検討してみるのもいいかもしれない。

[追記] EACH_TOP_K でパフォーマンスが良くなるケース

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0