イクジニアブログ

育児 + エンジニア = イクジニア

CDH5.4 Hiveでwhere句が効かない現象について

うるう秒が迫ってきてビクビクしているにいやんです。こんばんわ。

とりあえず、うるう秒の時はHadoopクラスタ止めておくかな、どうしよかな・・・

前回CDH5.4でカラムずれが起きるバグの事を書いたのですが、同じようにleft outer joinを使った際にwhere句が効かないというか、where句が代入になるというか、なんといえば良いかわからないバグに遭遇したので、まとめてみました。

以下のような4つのテーブルを作成します。

create table t_1 (
aid int,
bid int,
t_1name string);

create table t_2 (
aid int,
bid int,
t_2name string);

create table t_3 (
aid int,
bid int,
t_3name string);

create table t_4 (
aid int,
bid int,
t_4name string);

t-1からt-3までには以下のデータを

1       2
1       2
1       2

t-4には以下のデータを入れます

1       2
1       2
1       2       moge

それで以下のSQLでselect

select
  d.aid,
  d.bid,
  d.t_4name
from t_1 a
left outer join
  t_2 b
on 
  (a.aid = b.aid and b.t_2name = "test")
left outer join
  t_3 c
on
  a.bid = c.bid
left outer join
  t_4 d
on
  a.aid = d.aid
where
  d.t_4name = "hoge";

d.t_4name = "hoge"にはどのデータもひっかからないので、このselect文の期待値は何も表示されないですが、このSQLの結果は・・・・

1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge
1       2       hoge

hoge キタ━━━(゚∀゚).━━━!!!

d.t_4nameに入ってるデータは「moge」なのですが、なぜかそれが「hoge」にかわり、結果が返されました・・・orz

explainも取ってみたいのですが、以下のようになってました。

STAGE DEPENDENCIES:
  Stage-8 is a root stage
  Stage-6 depends on stages: Stage-8
  Stage-0 depends on stages: Stage-6

STAGE PLANS:
  Stage: Stage-8
    Map Reduce Local Work
      Alias -> Map Local Tables:
        b 
          Fetch Operator
            limit: -1
        c 
          Fetch Operator
            limit: -1
        d 
          Fetch Operator
            limit: -1
      Alias -> Map Local Operator Tree:
        b 
          TableScan
            alias: b
            Statistics: Num rows: 1 Data size: 15 Basic stats: COMPLETE Column stats: NONE
            Filter Operator
              predicate: (t_2name = 'test') (type: boolean)
              Statistics: Num rows: 0 Data size: 0 Basic stats: NONE Column stats: NONE
              HashTable Sink Operator
                keys:
                  0 aid (type: bigint)
                  1 aid (type: bigint)
                  2 aid (type: bigint)
        c 
          TableScan
            alias: c
            Statistics: Num rows: 1 Data size: 15 Basic stats: COMPLETE Column stats: NONE
            HashTable Sink Operator
              keys:
                0 _col1 (type: bigint)
                1 bid (type: bigint)
        d 
          TableScan
            alias: d
            Statistics: Num rows: 1 Data size: 19 Basic stats: COMPLETE Column stats: NONE
            HashTable Sink Operator
              keys:
                0 aid (type: bigint)
                1 aid (type: bigint)
                2 aid (type: bigint)

  Stage: Stage-6
    Map Reduce
      Map Operator Tree:
          TableScan
            alias: a
            Statistics: Num rows: 0 Data size: 15 Basic stats: PARTIAL Column stats: NONE
            Map Join Operator
              condition map:
                   Left Outer Join0 to 1
                   Left Outer Join0 to 2
              keys:
                0 aid (type: bigint)
                1 aid (type: bigint)
                2 aid (type: bigint)
              outputColumnNames: _col1, _col12, _col13
              Statistics: Num rows: 2 Data size: 41 Basic stats: COMPLETE Column stats: NONE
              Map Join Operator
                condition map:
                     Left Outer Join0 to 1
                keys:
                  0 _col1 (type: bigint)
                  1 bid (type: bigint)
                outputColumnNames: _col12, _col13
                Statistics: Num rows: 2 Data size: 45 Basic stats: COMPLETE Column stats: NONE
                Select Operator
                  expressions: _col12 (type: bigint), _col13 (type: bigint), 'hoge' (type: string)
                  outputColumnNames: _col0, _col1, _col2
                  Statistics: Num rows: 2 Data size: 45 Basic stats: COMPLETE Column stats: NONE
                  File Output Operator
                    compressed: false
                    Statistics: Num rows: 2 Data size: 45 Basic stats: COMPLETE Column stats: NONE
                    table:
                        input format: org.apache.hadoop.mapred.TextInputFormat
                        output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
                        serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
      Local Work:
        Map Reduce Local Work

  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

explainを見ると「d.t_4name = "hoge";」のwhere条件がなくなっています。

そして
「expressions: col12 (type: bigint), col13 (type: bigint), 'hoge' (type: string)」
ここを見てもらえればわかるように「d.t_4name」をselectした場所が「hoge」に変わってしまってます。

この現象が起きる条件としてわかってる範囲では以下の5つの条件が必要になるようです。

  • 4つ以上のテーブルをleft outer joinでつなぐ

  • 複数のkeyでjoinする(今回ではaidとbid)

  • 複数のkeyのjoinを入れ子にする。(aidでjoinの後にbidでjoinしてからaidでjoinの様に)

  • どこかのon句にkeyのjoin以外の条件を追加(今回では「b.t_2name = "test"」)

  • 入れ子にした後のテーブルのカラムでwhere句を生成

HiveのJIRAも検索したのですが、同じ様な現象は発見出来ませんでした。(どなたか知ってたら教えてください)

前回に紹介したカラムずれといい、今回の紹介のバグといい、left outer joinちょっと怖いですね・・・

早く治ります様に(ー人ー)

-- 2015/07/08 追記
CDH5.4.3では直っている事を確認出来ました。