Kudu:spark读取数据写入kudu通用方法

文章目录

  • 通用方法
  • 创建表并写入数据
  • 读取数据
  • spark集成kudu的已知问题和限制
  • Java方法调用kudu示例

通用方法

import org.apache.spark.sql._
import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._
import org.apache.kudu.client._
import collection.JavaConverters._
import org.apache.kudu.spark.kudu.KuduContext
/**
 * 将DataFrame中kudu不支持的列类型转为String类型
 */
def fmt_df(df: DataFrame) = {
  val new_sch = fmt_schema(df.schema, Seq())
  var d = df
  new_sch.foreach {
    case StructField(name: String, dataType: DataType, _, _) =>
      d = d.withColumn(name, col(name).cast(dataType))
  }
  d
}

/**
 * 将schema转为kudu可以建表的schema。具体做以下事情:
 * 1. 主键不能为空
 * 2. 把kudu不支持的数据类型转为String
 * 3. 所有列名转为小写字母
 */
def fmt_schema(sch: StructType, pk: Seq[String]) = {
  var arr = Array[StructField]()
  sch.foreach {
    case StructField(name: String, dataType: DataType, nullable: Boolean, metadata: Metadata) =>
      val name_ = name.toLowerCase
      val dataType_ = dataType match {
        case DateType       => StringType
        case t: DecimalType => StringType
        case _              => dataType
      }

      var nullable_ = nullable
      pk.foreach(k => if (k.toLowerCase == name_) nullable_ = false)
      arr = arr :+ new StructField(name_, dataType_, nullable_, metadata)
  }
  StructType(arr)
}

创建表并写入数据

def createTableTest() {
  val kudu_master = "master:7051,slave1:7051,slave2:7051"
  val kuduContext = new KuduContext(kudu_master, spark.sparkContext)

  val df = spark.table("hive_test")
  val data = df.drop("columns_kudu_dont_supports")

  val pks = Seq("primary", "key").map(_.toLowerCase)

  val table_name = "kudu_test"
  // 创建表结构,并不写入数据
  kuduContext.createTable(
    table_name, fmt_schema(data.schema, pks), pks,
    new CreateTableOptions()
      .setNumReplicas(3)
      .addHashPartitions(pks.asJava, 10))

  val res = fmt_df(data)
  // 写入数据
  kuduContext.upsertRows(res, table_name)
}

另一种写入数据的方法

// Data can also be inserted into the Kudu table using the data source, though the methods on
// KuduContext are preferred
// NB: The default is to upsert rows; to perform standard inserts instead, set operation = insert
// in the options map
// NB: Only mode Append is supported
df.write
  .options(Map("kudu.master" -> kudu_master , "kudu.table" -> table_name))
  .mode("append")
  .format("kudu").save

读取数据

val d = spark.read
  .options(Map("kudu.master" -> kudu_master, "kudu.table" -> table_name))
  .format("kudu").load

若语句报错java.lang.ClassNotFoundException: kudu.DefaultSource

则请确认引入的jar包版本(用1.9.0版本,更早版本会报错):

spark-shell --packages org.apache.kudu:kudu-spark2_2.11:1.9.0
# 或
spark-shell --jars kudu-spark2_2.11-1.9.0.jar

maven仓库地址:https://mvnrepository.com/artifact/org.apache.kudu/kudu-spark2_2.11/1.9.0

spark集成kudu的已知问题和限制

https://kudu.apache.org/docs/developing.html#_spark_integration_known_issues_and_limitations

  • 注册为临时表时,必须为具有大写字母或非 ASCII 字符的名称的 Kudu 表分配备用名称。

  • 具有包含大写字母或非 ASCII 字符的列名称的 Kudu 表, 不能与 SparkSQL 一起使用。 Columns 可能在 Kudu 更名为解决这个问题。

  • <>OR 谓词不被推送到 Kudu ,而是将在 Spark 的evaluate过程中执行, 只有具有后缀通配符的 LIKE 谓词才被推送到Kudu执行,这意味着 LIKE "FOO%"语句被下推到Kudu,而 LIKE "FOO%BAR"这样的语句不会。

  • Kudu 不支持 Spark SQL 支持的所有类型,例如 Date , Decimal 和复杂类型。

  • Kudu 表只能在 SparkSQL 中注册为临时表。 不能使用 HiveContext 查询 Kudu 表。

Java方法调用kudu示例

https://github.com/apache/kudu/blob/master/examples/java/java-example/src/main/java/org/apache/kudu/examples/Example.java

你可能感兴趣的:(kudu)