Hive接続によるデカルトセットの生成

4841 ワード

hiveの使用中にこのような例外が発生しました.
FAILED: ParseException line 1:18 Failed to recognize predicate 'a'. Failed rule: 'kwInner' in join type specifier
実行されるhql文は次のとおりです.
[[email protected] ~]# hive -e 'select a.* from t a, t b where a.id=b.id'
異常情報からエラーの原因がわかりにくいロゴにも詳細な異常対戦情報は印刷されていません.jdbcでhive-server 2を接続すると、hive-server 2に次の異常情報が表示されます.
13/10/17 09:57:48 ERROR ql.Driver: FAILED: ParseException line 1:18 Failed to recognize predicate 'a'. Failed rule: 'kwInner' in join type specifier

org.apache.hadoop.hive.ql.parse.ParseException: line 1:18 Failed to recognize predicate 'a'. Failed rule: 'kwInner' in join type specifier

	at org.apache.hadoop.hive.ql.parse.ParseDriver.parse(ParseDriver.java:446)
	at org.apache.hadoop.hive.ql.Driver.compile(Driver.java:441)
	at org.apache.hadoop.hive.ql.Driver.compile(Driver.java:349)
	at org.apache.hadoop.hive.ql.Driver.compileAndRespond(Driver.java:355)
	at org.apache.hive.service.cli.operation.SQLOperation.prepare(SQLOperation.java:95)
	at org.apache.hive.service.cli.operation.SQLOperation.prepare(SQLOperation.java:76)
	at org.apache.hive.service.cli.operation.SQLOperation.run(SQLOperation.java:114)
	at org.apache.hive.service.cli.session.HiveSessionImpl.executeStatement(HiveSessionImpl.java:194)
	at org.apache.hive.service.cli.CLIService.executeStatement(CLIService.java:155)
	at org.apache.hive.service.cli.thrift.ThriftCLIService.ExecuteStatement(ThriftCLIService.java:191)
	at org.apache.hive.service.cli.thrift.TCLIService$Processor$ExecuteStatement.getResult(TCLIService.java:1193)
	at org.apache.hive.service.cli.thrift.TCLIService$Processor$ExecuteStatement.getResult(TCLIService.java:1)
	at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:39)
	at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39)
	at org.apache.hive.service.cli.thrift.TSetIpAddressProcessor.process(TSetIpAddressProcessor.java:38)
	at org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:206)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
異常情報からhql文をコンパイルして構文解析を行う際にエラーが発生したことがわかりますが、いったいなぜFailed rule: 'kwInner' in join type specifierという異常情報が発生したのでしょうか.
eclipseでキーワードを検索すると、対応するコードが見つかりません.Hive.gでキーワード「kwInner」を検索すると、次のように表示されます.
joinToken
@init { msgs.push("join type specifier"); }
@after { msgs.pop(); }
    :
      KW_JOIN                     -> TOK_JOIN
    | kwInner  KW_JOIN            -> TOK_JOIN
    | KW_CROSS KW_JOIN            -> TOK_CROSSJOIN
    | KW_LEFT  KW_OUTER KW_JOIN   -> TOK_LEFTOUTERJOIN
    | KW_RIGHT KW_OUTER KW_JOIN   -> TOK_RIGHTOUTERJOIN
    | KW_FULL  KW_OUTER KW_JOIN   -> TOK_FULLOUTERJOIN
    | KW_LEFT  KW_SEMI  KW_JOIN   -> TOK_LEFTSEMIJOIN
    ;
hiveがサポートする接続には、次のものが含まれています.
  • join
  • inner join
  • cross join (as of Hive 0.10)
  • left outer join
  • right outer join
  • full outer join
  • left semi join
  • kwInnerはなぜ小文字なのか、その意味は何なのか.キーワードを検索し、次のコードを見つけます.
    kwInner
    :
    {input.LT(1).getText().equalsIgnoreCase("inner")}? Identifier;
    
    上の大まかな意味は、左に入力した内容を見つけて、その値が大文字と小文字を無視した場合にinnerに等しいかどうかを判断することです.hql文にinnerキーワードが欠けていることを意味しますか?hql文を次のように変更して実行します.
    [[email protected] ~]#  hive -e 'select a.* from t a inner join t b where a.id=b.id'
    
    修正したhql文は正常に動作し、内部接続になります. JION ON key WHERE 。Hive自体はデカルトセットをサポートしておらず,select T1.*, T2.* from table1, table2という文法は使用できない.しかし、デカルトセットを使用する必要がある場合は、次の構文で同じ効果を実現できます.
    select T1.*, T2.* from table1 T1 join table2 T2 where 1=1;
    
    注意HiveのStrictモードではこの構文は使用できません.これはデカルトセットが生成され、このモードではデカルトセットの生成が禁止されるためです.set hive.mapred.mode=nonstrict;を非strictモードに設定するか、whereをon接続に変更する必要があります.
    select T1.*, T2.* from table1 T1 join table2 T2 on  T1.id=T2.id;
    
    Strict Modeについて
    Hiveの厳格なモードは、ユーザーが発行した(問題がある可能性がある)クエリーが無意識に悪影響を及ぼすことを防止します.hive.mapred.modeをstrictに設定すると、3つのタイプのクエリーを禁止できます.
    1)一つのパーティション表において、WHERE条件に具体的なパーティションが明示されていない場合、これは許されない.言い換えれば、パーティション表上の全表スキャンは許されない.この制限の理由は、パーティション・テーブルが通常非常に大きなデータセットを持ち、データの増加が迅速である可能性があるためであり、このような大きなテーブルをフル・テーブル・スキャンすると、大量のリソースが消費され、WHEREフィルタ条件にパーティションが具体的に指定されてこそ、成功したクエリーを実行することができる.
    2)、2つ目は、ORDER BYのソート要件があるがLIMIT文がないHiveQLクエリの実行を禁止することである.ORDER BYグローバルクエリは、すべてのクエリ結果を単一のreducerでソートするため、大きなデータセットをソートすると予想外の実行時間になり、limit条件を加えてクエリを正常に実行する必要があります.
    3)、3つ目はデカルトセットの生成を禁止することです.JION連続クエリでON接続keyがなく、WHERE条件文でデカルトセットが生成されますので、JOIN…ON文に変更する必要があります.