KUDU基本知识

1.通过impala来操作kudu,impala的元数据放在hive的metastore服务里,impala-shell 命令行开启shell操作。

2.在impala里创建kudu表,需要impala的外部表与kudu的表做映射:

kudu表基于其partition方法被拆分成多个分区,每个分区就是一个tablet,一张kudu表所属的所有tablets均匀分布并存储在tablet servers的磁盘上。因此在创建kudu表的时候需要声明该表的partition方法,同时要指定primary key作为partition的依据。Kudu中的分区方法主要有两种:partition by hash和partition by range。

-- 按照id 切分,partition by hash
create external table tab4
(
id int,
name string,
delete_state string,
time_stamp string,
primary key (id)
)
partition by hash (id) partitions 2
stored as kudu
tblproperties ('kudu.master_addresses'='bigdata03:7051,bigdata05:7051,bigdata07:7051', 'kudu.table_name'='tab4');
--tblproperties  在将impala里的外部表与kudu里的表进行映射
-- 按照班级分类  partition by range
create table testinkudu2(
classes int,
namestring,
ageint,
primarykey(classes,name))
partition by range(classes)(
                            partition value = 1,
                            partition value = 2,
                            partition value =3,
partitionvalue =4)
stored as kudu;

 

create external table xxx (id int ,......,primary key (id)) partition by hash (id) partitions 2 stored as kudu;

create external table xxx (id int ,......,primary key (class)) partition by range(partition value = 1,partition value = 2)  stored as kudu;

3.基本语法

-- insert (3种)
1. insert into testinkudu values(‘a’, 12);
2. insert into testinkudu values(‘a’, 12),(‘b’, 13),(‘c’, 14);
3. insert into testinkudu select * from other_table;

-- update
kudu表的update操作不能更改主键的值,其他与标准sql语法相同。

-- upsert
对于upsert into testinkudu values(‘a’, 12);如果指定的values中的主键在testinkudu中已经存在,则执行update语义,反之,执行insert语义。(侦察主键是否已存在)

-- delete
与标准sql语法相同。

4.Kudu之Scala版本API

建表:

-- 建表
// 创建kudu连接
val kuduClient = new KuduClient.KuduClientBuilder("172.20.85.29:7051").build()
// 设置表名
val tableName = "kudu_test"
// 创建列
val colums = List[ColumnSchema]((new ColumnSchema.ColumnSchemaBuilder("name", Type.STRING).key(true).nullable(false).build()),
      (new ColumnSchema.ColumnSchemaBuilder("age", Type.INT64).nullable(true).build()),
      (new ColumnSchema.ColumnSchemaBuilder("city", Type.STRING).nullable(true).build()))
val schema: Schema = new Schema(colums.asJava)
// 设置hash分区
val cto: CreateTableOptions = new CreateTableOptions()
cto.setRangePartitionColumns(List("name").asJava).setNumReplicas(3)
// 执行建表语句
kuduClient.createTable(tableName, schema, cto)
// 关闭kudu连接
kuduClient.close()

kuduClient API   insert/update/upsert/delete

// 创建kudu连接
val kuduClient = new KuduClient.KuduClientBuilder("172.20.85.29:7051").build()
// 设置表名  
val tableName = "kudu_test"
// 获得表的连接
val kuduTable = kuduClient.openTable(tableName)
// 开启一个会话
val  session = kuduClient.newSession()
// session.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH)   # (别开,实时中易掉数据)
 
---------------------------------------getColumns----------------------------------------
//获取字段信息
val columns = kuduTable.getSchema.getColumns.toArray()

---------------------------------------insert----------------------------------------
// 创建插入对象并设置插入数据
val insert = kuduTable.newInsert()
val row = insert.getRow()
row.addString(0, "Ronnie")
row.addInt(1, 21)
row.addString(2, "beijing")
//执行插入语句
session.apply(insert)

---------------------------------------update----------------------------------------
 // 创建updata对象
val update = kuduTable.newUpdate()
val rowUpdata = update.getRow()
rowUpdata.addString("name", "nnnn")
rowUpdata.addInt("age", 22)
rowUpdata.addString("city", "ddddd")
// 同步数据并关闭会话    
session.apply(update)

---------------------------------------upsert----------------------------------------
// 创建upsert对象
val upsert = kuduTable.newUpsert()
val rowUpsert = upsert.getRow()
rowUpsert.addString("name", "nnnn")
rowUpsert.addInt("age", 19)
rowUpsert.addString("city", "mmmm")
// 执行upsert操作
session.apply(upsert)

---------------------------------------批量upsert----------------------------------------
for (indexCol <- 0 until columns.length) {
  if (columns(indexCol).toString.contains("int32")) {
    // 创建插入对象并设置插入数据
    row.addInt(indexCol, logResult(indexCol).toInt)
  }
  else if (columns(indexCol).toString.contains("string")) {
    row.addString(indexCol, logResult(indexCol))
  }
  else if (columns(indexCol).toString.contains("double")) {
    row.addDouble(indexCol, logResult(indexCol).toDouble)
  }
  else if (columns(indexCol).toString.contains("bool")) {
    row.addBoolean(indexCol, logResult(indexCol).toBoolean)
  }
// 执行upsert操作
session.apply(upsert)


---------------------------------------select----------------------------------------

// 设置查询条件
val schema = kuduTable.getSchema()
val name = KuduPredicate.newComparisonPredicate(schema.getColumn("name"), KuduPredicate.ComparisonOp.EQUAL, "Ronnie")
val age = KuduPredicate.newComparisonPredicate(schema.getColumn("age"), KuduPredicate.ComparisonOp.LESS, 22)
val city = KuduPredicate.newComparisonPredicate(schema.getColumn("city"), KuduPredicate.ComparisonOp.EQUAL, "beijing")
// 执行查询操作
val builder = kuduClient.newScannerBuilder(kuduTable)
        .setProjectedColumnNames(List("name", "age", "city").asJava)
        .addPredicate(name)
        .addPredicate(age)
        .addPredicate(city).build()
while (builder.hasMoreRows()) {
   val results = builder.nextRows()
      while (results.hasNext()) {
        val result = results.next()
        System.out.println(result.getLong("name") + "_" + result.getInt("age") + "_" + result.getString("city"))
    }
// 关闭kudu连接
kuduClient.close()

---------------------------------------delete----------------------------------------
// 创建删除对象并指定要删除的行
val delete = kuduTable.newDelete()
delete.getRow().addString("name", "Ronnie")
// 执行删除操作
session.apply(delete)


// 同步数据,关闭会话
session.flush()
session.close()

 5. kudu插入数据的三种刷新策略

  • AUTO_FLUSH_SYNC   (默认)
  • AUTO_FLUSH_BACKGROUND
  • MANUAL_FLUSH  速度最快,但是实时的情况下容易发生数据丢失。(调用  KuduSession.apply() 方法后,会返回的非常快,但是写操作不会发送,直到用户使用flush()函数,如果缓冲区超过了配置的空间限制,KuduSession.apply()函数会返回一个错误。所以缓冲区里的数据会因为断电或其他业务,在还没有flush的情况下丢失)

6.kudu 与 impala 与 hdfs 的纠葛

impala中创建kudu表的话,可以在impala中看到kudu表,但是使用 kudu java api创建kudu表的话,impala看不到kudu表,只能kudu web ui看到,因此也只能使用 kudu java api删除该表。
因此此时需要进入impala-shell创建impala外部映射表映射Kudu表,创建impala外部映射表之后,就同时会在hdfs的/user/hive/warehouse路径下创建同名文件夹。
impala中创建kudu表和impala外部映射表的话,两者都会在hdfs的/user/hive/warehouse路径下创建同名文件夹,并且两者都能在impala-shell中查看到表。
如果使用 kudu java api创建kudu表的话,并不会在hdfs的/user/hive/warehouse路径下创建同名文件夹,并且impala-shell中查看不到该kudu表。

7.impala命令刷新元数据
    impala-shell 命令进入交互界面 执行 invalidate metadata; 命令刷新元数据 
    Hue的wen页面中,在impala执行sql的窗口 执行 invalidate metadata; 命令刷新元数据 

8.kudu导入导出

导出 kudu表数据 为csv文件
	impala-shell中 导出kudu表数据为csv文件,或者说是通过impala的外部映射表把kudu表数据导出为csv文件
	impala-shell -q "select * from rawdata.event_wos_p1 LIMIT 100" -B --output_delimiter=","  -o /home/gzp/event_wos_p1.csv
把csv文件 导入到 kudu表中
	1.首先impala中要创建带分隔符的临时表,即impala中创建的表带有row format delimited fields terminated by ',';
		create table event_wos_p1_temp(day int,...)row format delimited fields terminated by ',';
	2.使用 kudu java/scala api 创建kudu表 或 impala中  创建kudu表
	3.impala中 创建映射kudu表 的impala外部 映射表
	4.INSERT INTO impala外部映射表/kudu表 SELECT * FROM 带分隔符的临时表;
		INSERT INTO event_wos_p1 SELECT * FROM event_wos_p1_temp;

9.kudu的应用场景

  • kudu是什么?

简单来说:kudu是一个与hbase类似的列式存储分布式数据库。

官方给kudu的定位是:在更新更及时的基础上实现更快的数据分析

  • 为什么需要kudu?

hdfs与hbase数据存储的缺点

目前数据存储有了HDFS与hbase,为什么还要额外的弄一个kudu呢?

HDFS:使用列式存储格式Apache Parquet,Apache ORC,适合离线分析,不支持单条纪录级别的update操作,随机读写性能差

HBASE:可以进行高效随机读写,却并不适用于基于SQL的数据分析方向,大批量数据获取时的性能较差。

正因为HDFS与HBASE有上面这些缺点,KUDU较好的解决了HDFS与HBASE的这些缺点,它不及HDFS批处理快,也不及HBase随机读写能力强,但是反过来它比HBase批处理快(适用于OLAP的分析场景),而且比HDFS随机读写能力强(适用于实时写入或者更新的场景),这就是它能解决的问题。

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值