tchikuba's blog

クリエイティブが輝ける組織をエンジニアリングする

td-clientを使ってHiveより早いPrestoクエリを実行する方法をrakeタスクで

最近、Hadoop(Tresure Data)と格闘してます。

td-clientを使ってTresureDataからデータを取得するrakeタスクを書いててHiveクエリだと遅いのでPresto使いたいなと思うことがありました。 td-clientのREADMEなど公式情報をざっと確認したところ見当たりませんでしたが、 td-client-rubyのソースコードを見たら案の定クエリタイプを指定するインタフェースがありました。

https://github.com/treasure-data/td-client-ruby/blob/master/lib/td/client.rb#L182

client.rb#L182付近gist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  # @param [String] db_name
  # @param [String] q
  # @param [String] result_url
  # @param [Fixnum] priority
  # @param [Fixnum] retry_limit
  # @param [Hash] opts
  # @return [Job]
  def query(db_name, q, result_url=nil, priority=nil, retry_limit=nil, opts={})
    # for compatibility, assume type is hive unless specifically specified
    type = opts[:type] || opts['type'] || :hive
    raise ArgumentError, "The specified query type is not supported: #{type}" unless [:hive, :pig, :impala, :presto].include?(type)
    job_id = @api.query(q, type, db_name, result_url, priority, retry_limit, opts)
    Job.new(self, job_id, type, q)
  end

上記の通りqueryメソッドの第5引数にoptsというハッシュで指定するオプションがあり、 type: :prestoな指定をするとHiveではなくPrestoでクエリが発行されます。

以下、rakeタスクでのサンプルコードです。

rakeタスクでのサンプルコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace :execute do
  desc 'download treasure data by presto'
  task presto: :environment do
    apikey = 'your api key'
    db = 'your_db_name'
    query = 'select count(*) from your_table_name'
    client = TreasureData::Client.new apikey
    job = client.query db, query, nil, nil, nil, type: :presto
    until job.finished?
      sleep 2
      job.update_status!
    end
    job.update_status!
    p job.result if job.finished?
  end
end
実行
1
bin/rake execute:presto
結果
1
[[100]] # your_db_name.your_table_nameの件数

上記のように単純なクエリの場合、Hiveだとパフォーマンス的にwebアプリ等から動的に取得するのが 現実的に時間がかかりすぎたクエリでもPrestoであれば動的にデータ取得可能なので利用の幅が広がりますね。

合わせて読みたい