Spark-Schema分析--doublehappy

schema

1.如果你使用Spark获取到数据之后 使用它的Schema

可以用来做什么??
最简单的:
1.自动创建 Hive表  分区表或者 普通的表
2.判断 数据源 字段变更问题  进而修改 Hive表

这个东西非常有用:
	1.如果上游数据源 字段变更了 没有通知你  导致数据 入不进去数仓 或者
	直接把锅摔给你 你无力解释 
	那么你可以通过修改一套通用的代码 让使用者感知不到 字段变更了 这岂不是美滋滋
   
   2. 这个 比使用 Hive方式 写脚本 操作方便 
     Hive倒入数据 上游发生变更 修改起来 真的是  恨不得对上游数据人员骂街了

大家都是出来赚钱 真的没有必要勾心斗角  对我而言 老老实实干活学技术 现在毕竟年轻 
赚点小钱 回家种地去了。职场文化太深奥 不适合我这个山村憨批。
Schema:
	是 StructType 类型

StructType:
	是StructType(fields: Seq[StructField]) 
	里面有 	StructField
	你可以理解为 :
		StructType 是一张表
		StructField 就是 表里面的字段

StructField:
	/**
 * A field inside a StructType.
 * @param name The name of this field.
 * @param dataType The data type of this field.
 * @param nullable Indicates if values of this field can be `null` values.
 * @param metadata The metadata of this field. The metadata should be preserved during
 *                 transformation if the content of the column is not modified, e.g, in selection.
 *
 * @since 1.3.0
 */
@InterfaceStability.Stable
case class StructField(
    name: String,
    dataType: DataType,
    nullable: Boolean = true,
    metadata: Metadata = Metadata.empty) 

StructField:
	name: String,
    dataType: DataType,
    nullable: Boolean = true,
    metadata: Metadata 

就是这点东西,拿到这些东西 就可以干跟多事情啦!

测试:

package com.offline.task

import com.common.util.ContextUtil
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types.StructType

object Test {

  def main(args: Array[String]): Unit = {

    System.setProperty("HADOOP_USER_NAME", "hive")
    val spark: SparkSession = ContextUtil.getSparkSession(this.getClass.getSimpleName)

    val dbase = spark.sparkContext.getConf.get("spark.source.hive.dbabase","doublehappy_erp")
    val table = spark.sparkContext.getConf.get("spark.source.hive.table","doublehappy_depothead")

    val schema: StructType = spark.table(s"${dbase}.ods_${table}").schema


    println("schema : " + schema)
//    schema.map()



    spark.stop()
  }

}

结果:
schema : 
StructType(StructField(Id,LongType,true), 
StructField(Type,StringType,true), 
StructField(SubType,StringType,true), 
StructField(ProjectId,LongType,true), 
StructField(DefaultNumber,StringType,true), 
StructField(Number,StringType,true), 
StructField(OperPersonName,StringType,true), 
StructField(CreateTime,TimestampType,true),
 StructField(OperTime,TimestampType,true), 
 StructField(OrganId,LongType,true), 
 StructField(HandsPersonId,LongType,true),
  StructField(AccountId,LongType,true), 
  StructField(ChangeAmount,DecimalType(24,6),true), 
  StructField(AllocationProjectId,LongType,true), 
  StructField(TotalPrice,DecimalType(24,6),true),
   StructField(PayType,StringType,true), 
   StructField(Remark,StringType,true), 
   StructField(Salesman,StringType,true), 
   StructField(AccountIdList,StringType,true), 
   StructField(AccountMoneyList,StringType,true), 
   StructField(Discount,DecimalType(24,6),true), 
   StructField(DiscountMoney,DecimalType(24,6),true), 
StructField(DiscountLastMoney,DecimalType(24,6),true), 
StructField(OtherMoney,DecimalType(24,6),true), 
   StructField(OtherMoneyList,StringType,true), 
   StructField(OtherMoneyItem,StringType,true), 
   StructField(AccountDay,IntegerType,true), 
   StructField(Status,StringType,true), 
   StructField(LinkNumber,StringType,true), 
   StructField(tenant_id,LongType,true), 
   StructField(delete_Flag,StringType,true), 
   StructField(UpdateTime,TimestampType,true))


可以拿到你的 data:
	1.字段名字  name
	2. 字段类型  DataType

这两个就足够了

注意:
DecimalType(24,6)
如果不是24,6  对应别的 你如何创建呢??

数据写入Hive 分区表

首先写入Hive分区表的方式真的是多了去了:

但是 选一个最好的方式:
	1.spark.sql()   里面直接 insert overwrite 方式 对吧 最简单  (但是 这样代码就写死了 换一个业务就很费劲)
	2.api的方式 : 
		1. 分区表的 路径下 方式 :
		       1.写到分区路径 + MSCK repair table    :append
		       2.使用 add patition 方式   : append
		2. insertInto 方式    : overwrite
	
	我个人使用 api的方式 或者 sql的方式 

但是哈:
	api方式 是有坑的:
		1.数据的幂等性 你如何保证 
			1.insertInto 没有问题
		    2.你写入分区表写路径的方式 一定是append的 ,sql方式 是overwrite的对吧
问题就出现在这:
	写入分区表写路径的方式!!!数据幂等性你如何保证 
	解决 :
		这两种 你都可以 :
			先删掉之前路径 再 写数据   
			再 :
				msck 或者 add partition 方式 对吧

注意:
	drop table 正常情况下:
		1.分区里的数据同时也被删掉了对吧 
		但是 add partition 方式 你删表 但是路径 和里面的数据 是不会被删掉的哟!!! 
		
api  写路径方式问题:
   1.幂等性问题:
	    解决思路都是 先drop partition  再补数据对吧(这是大部分人的理解)

但是:
	alter table ods_ruozedata_depothead_update drop partition (UpdateDay='2020-03-20');

这个操作 真的会把 hdfs上的数据删掉吗????

测试:
先:
alter table ods_ruozedata_depothead_update drop partition (UpdateDay='2020-03-20');

在这里插入图片描述

查看HDFS路径:
[hive@hadoop003 ~]$ hadoop fs -ls  /user/hive/warehouse/ruozedata_erp.db/ods_ruozedata_depothead_update/UpdateDay=2020-03-20
Found 1 items
-rwxrwx--x+  1 hive hive       7895 /user/hive/warehouse/ruozedata_erp.db/ods_ruozedata_depothead_update/UpdateDay=2020-03-20/part-00000-33d18a8c-0e94-417e-be2a-c00581721545.c000.snappy.parquet
[hive@hadoop003 ~]$ 


所以呀:
	不要别人说什么你信什么,
	这样删完了 确实查不到数了。

在这里插入图片描述

这里只能使用:
	ALTER TABLE ods_ruozedata_depothead_update ADD PARTITION (UpdateDay='2020-03-20')
LOCATION '/user/hive/warehouse/ruozedata_erp.db/ods_ruozedata_depothead_update/UpdateDay=2020-03-20';


恢复数据

在这里插入图片描述

这里还有一个有趣的事情:
	1.使用 add partition 后 
	 drop table  是删不掉 hdfs上的数据的 
正常的 drop table 数据同时也被删掉的 (内部表)

这里 就不会被删掉 


所以:写路径的方式 写Hive 保证幂等性
	思路是: add partition
		1.dropPartition
		2.deleteOldPartitionDir
		3.写数据
		4.addPartition
   思路:msck
      1.deleteOldPartitionDir
      2.写数据
      3.msck


我会选择 add partition 方式 因为drop table  数据也不会被删掉

只需要:
	重新建表 + add partition 就可以恢复数据了
   
今天也是无聊:
	把数仓的代码完整的重新 写了一遍 补充了早期一致没有加的东西!!
所以学习大数据 思路+架构设计 真的很重要 要不然 真的是 劳民伤财呀 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章