使用SparkSQL从HBase获取所有记录

时间:2015-07-06 13:30:03

标签: apache-spark hbase apache-spark-sql

我正在尝试从Hbase表中读取所有记录。以下是代码段。

    SparkContext sparkContext = new SparkContext(conf);

    SQLContext sqlContext = new SQLContext(sparkContext);

    Configuration hbaseConf = HBaseConfiguration.create();

    hbaseConf.set("hbase.master", "localhost:60000");
    hbaseConf.setInt("timeout", 120000);
    hbaseConf.set("hbase.zookeeper.quorum", "localhost");
    hbaseConf.set("zookeeper.znode.parent", "/hbase-unsecure");
    hbaseConf.set(TableInputFormat.INPUT_TABLE, "Test");

    DataFrame df = sqlContext.createDataFrame(sparkContext.newAPIHadoopRDD(hbaseConf, TableInputFormat.class, ImmutableBytesWritable.class, Result.class), TestBean.class);

    df.registerTempTable("TempTest");
    df.show();

df.show()我收到错误

java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

任何指针,我为什么要面对这个问题。

1 个答案:

答案 0 :(得分:0)

您正在尝试从由对组成的RDD创建DataFrame:

org.apache.hadoop.hbase.io.ImmutableBytesWritable     
org.apache.hadoop.hbase.client.Result

您需要阅读hBaseRDD:

val hBaseRDD = sc.newAPIHadoopRDD(hbaseConf, classOf[TableInputFormat], 
  classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
  classOf[org.apache.hadoop.hbase.client.Result]);

然后将(ImmutableBytesWritable,Result)元组转换为Result的RDD:

val resultRDD = hBaseRDD.map(tuple => tuple._2) 

然后转换为可以转换为DataFrame的行的RDD。

作为一个例子,我们假设您有一个HBase表,其中一个键包含两个值'value1_value2',您可以使用以下方法解析Key(由'_'分配):

val keyValueRDD = resultRDD.map(result =>     (Bytes.toString(result.getRow()).split("_")(0),   Bytes.toString(result.getRow()).split("_")(1), Bytes.toFloat(result.value())))

现在,您可以使用“_”分隔键中的值创建数据框:

   import sqlContext.implicits._
   val df = keyValueRDD.toDF("value1", "value2");
   df.registerTempTable("Table")
   sqlContext.sql("SELECT * FROM Table Limit 5").show()

为了将您的HBase表完全映射到DataFrame,您需要:

  1. 创建案例类 :(在您的对象之外)

     case class TestRow(rowkey: String, value1: String, value2: String, value3: Float, value4: Float)
    
  2. 将列系列定义为字节

    final val cfTest = "te"
    final val cfTestBytes = Bytes.toBytes(cfTest)
    
  3. 解析结果

      object TestRow {
        def parseTestRow(result: Result): TestRow = {
          val rowkey = Bytes.toString(result.getRow())
    
          val p0 = rowkey
          val p1 = Bytes.toString(result.getValue(cfTestBytes, Bytes.toBytes("currency")))
          val p2 = Bytes.toString(result.getValue(cfTestBytes, Bytes.toBytes("asat")))
          val p3 = Bytes.toFloat(result.getValue(cfTestBytes, Bytes.toBytes("m_aed")))
          val p4 = Bytes.toFloat(result.getValue(cfTestBytes, Bytes.toBytes("m_usd")))
          TestRow(p0, p1, p2, p3, p4)
        }
      }
    
  4. 创建数据框

    val hBaseRDD = sc.newAPIHadoopRDD(hbaseConf, classOf[TableInputFormat], 
    classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
    classOf[org.apache.hadoop.hbase.client.Result]);  
    
    val resultRDD = hBaseRDD.map(tuple => tuple._2)
    val testRDD = resultRDD.map(TestRow.parseTestRow)
    import sqlContext.implicits._
    val testDF = testRDD.toDF()
    testDF.registerTempTable("Test")
    sqlContext.sql("SELECT count(*) FROM Test").show()