TD_SESSIONIZEを使うときはサブクエリを使え
Webアクセスログ解析に超絶便利なTreasureDataのHive UDFのTD_SESSIONZE
ですが、使用する際には以下の前提があるので注意すること。
HiveQLがエラーになるわけではないが、狙ったようにセッションIDが付与されないので誤った集計結果になってしまいます。
- 引数に渡すカラムについて
DISTRIBUTE BY
、SORT BY
するサブクエリの直後に使用する
TD_SESSIONIZE
とは
同一アクセスと判断できるログに一意なセッションIDを付与してくれる関数。
string TD_SESSIONIZE(int/long unix_timestamp, int timeout, string sessionize_by)
- 第一引数:UNIX時刻
- 第二引数:同一セッションと判断する時間の範囲(単位は秒)
- 第三引数:同一セッションと判断するフィールド
具体例
サンプルで用意されているsample_datasetsのwww_accessテーブルを使って、
同じホスト(格納されているのはIPアドレス)からの1時間以内のアクセスを同じセッションとみなしたい場合、以下のように使います。
正しい使い方
SELECT
TD_SESSIONIZE(time,3600,host) AS session_id,
TD_TIME_FORMAT(time,'yyyy-MM-dd HH:mm:ss','JST') AS access_time,
host,
path
FROM (
SELECT
time,
host,
path
FROM
www_access
DISTRIBUTE BY host
SORT BY host,time
) t
結果には以下のようにセッションIDが付与されます。
session_id | access_time | host | path |
---|---|---|---|
bb368f01-9198-4718-9df3-51baeff9fce1 | 2014-10-04 05:39:00 | 100.111.144.44 | /item/computers/4323 |
bb368f01-9198-4718-9df3-51baeff9fce1 | 2014-10-04 06:11:08 | 100.111.144.44 | /item/software/759 |
ここで、重要なのが、
* TD_SESSIONIZE
の第三引数に使いたいフィールドでDISTRIBUTE BY
* TD_SESSIONIZE
の第三引数、第一引数に使いたいフィールドでSORT BY
をサブクエリで実行した後にTD_SESSIONIZE
を計算させること。
これは必須条件です。
誤った使い方
以下のようにTD_SESSIONIZE
をDISTRIBUTE BY
、 SORT BY
と同じレベルで実行するのはダメです。
SELECT
TD_SESSIONIZE(
time,
3600,
host
) AS session_id,
TD_TIME_FORMAT(time,
'yyyy-MM-dd HH:mm:ss',
'JST') AS access_time,
host,
path,
time
FROM www_access DISTRIBUTE BY host SORT BY host,time
HiveQLはエラーを出さずに正常終了するのですが、結果として
session_id | access_time | host | path |
---|---|---|---|
0f760fbe-4e7b-411a-b82d-4e44c0fd8cd8 | 2014-10-04 05:39:00 | 100.111.144.44 | /item/computers/4323 |
c2700830-f6e7-40af-9c78-4bc72eebba64 | 2014-10-04 06:11:08 | 100.111.144.44 | /item/software/759 |
のように、同じセッションとみなしてほしい(=同じホストで1時間以内のアクセス)レコードに異なるセッションIDが付与されてしまいます。
考察
落ち着いて考えると、それはそうだよなぁという感じ。
DISTRIBUTE BY
もSORT BY
もMapReduceにおいてReducerに集めるカラムのキー範囲や順番を制御するものです。
TD_SESSIONIZE
を実装するなら、事前にセッションを判定するキーが一箇所に集約されていて、しかも時間の順番にソートされている前提で、上から順番にレコードを読んでIDを付与していくのが一番楽です。
なので、一度MapReduceでその条件でレコードをグループ分けかつソートし、2段目のMapReduceのMapperでそれぞれTD_SESSIONIZE
してもらうのが自然。
辛いのは、ドキュメントの説明が
Similiar to TD_X_RANK, you need to ‘CLUSTER BY’ or ‘DISTRIBUTE BY’ the sessionize_by field, and sort by the unix_timestamp field.
となっていて、一見するとこの前提がわかりづらいこと。
Similar to TD_X_RANK
とあるのでそちらの説明を見ると、
You need to ‘CLUSTER BY’ or ‘ORDER BY’ within a sub query to use this feature.
とあるので、霊感で気づくのが要求されます。。。
2016/10/17 追記
TreasureDataのサポート経由で報告したところ、すぐにドキュメントを修正してくれました!
Similiar to TD_X_RANK, you need to CLUSTER BY or DISTRIBUTE BY the sessionize_by field, and SORT BY the unix_timestamp field within a sub query to use this feature.
まとめ
超絶便利な関数なので上記の点に気をつけて使いまくりましょう。
Author And Source
この問題について(TD_SESSIONIZEを使うときはサブクエリを使え), 我々は、より多くの情報をここで見つけました https://qiita.com/bwtakacy/items/4eaaf69c9350c2f230b7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .