Hive函数

Hive

  • 插入(装载)数据

    • 数据在本地或者hdfs中
	load data [local] inpath 'pathname' [overwrite] into table tablename [partition(column=xxx)]

insert 方法:

   insert方法:insert into tablename select xx,xx,xxx,xxx,[union all] select xxx,xxx,xx,xxx;

    from table_name insert overwrite table table_name [partition(xx,xx)] select xx,xx,xx;  典型的ETL模式

    insert into tablename values(coulmmn1 xxx,coulmn2 xx); 指定列插入  

    insert into tablename(name) value('Judy') 指定值插入

  • 发现插入:with t as(

select 5,‘mm’,‘1994-1-5’,array(‘study’)[union all] select xxx,xxx,xxx,

)

insert into emps select * from t

  • 导入数据csv文件

    CREATE EXTERNAL TABLE IF NOT EXISTS products (  
    product_id int,  
    product_category_id int,
    product_price float,
    product_image varchar(255)) 
    ROW FORMAT  serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
    with serdeproperties ("separatorChar"=",")  
    LOCATION '/data/retail_db/products';
    
  • 内部表 使用load data inpath ‘/x/x/’ into table table_name

  • 外部表 location 所指定的是文件的文件夹而不是文件

  • 导出数据

    export table table_name [partition(xx=xx,xx=xx)] to ‘/root/output’;

  • 创建表

    create table tablename as select * from xxx; CTS

    create table tablename as with 【结果集】 CTE

    create table tablename like tablename; 复制表结构不复制内容

  • row format serde ‘org.apache.hadoop.hive.serde2.OpenCSVSerde’ 把csv导入
    location ‘/shopping/’ 导入的是文件夹,只能放一个文件
    tblproperties (“skip.header.line.count”=“1”) 跳过首行

  • 查询数据

    单查 select xx from tablename where xxx;

    子查询:with a as(select * from tablename where xxx) select * from a;

    ​ : select * from (select * from xxx)a;

  • 删除表

    drop table if exists employee[with perge]------------------>with perge 直接删除【可选】否则会放在.Trash目录

  • alter table tabe_name rename to new_table_name; 更改表名

  • alter table table_name change old_name new_name string; 更改列名

  • alter table table_name add columns(work string); 添加列名

  • alter table table_name replace columns(name string); 替换列名

  • 内部表:

    HDFS中为所属数据库目录下的子文件夹

    数据完全由Hive管理,删除表(元数据)会删除数据

  • 外部表:

    数据保存在指定位置的HDFS路径中

    Hive不完全管理数据,删除表(元数据)不会删除数据

  • 静态分区(分区:提高查询性能)理解为文件夹

    创建表时添加分区字段 patitioned by(column,xxx) 此coulmn 在表中不存在

    alter table students add partition(sex=‘m’) partition(sex=‘f’);

    show partitions table_name;

    insert into students partition(sex=‘m’) select 1,‘zs’;

    alter table employee_test drop partition(year=2019,month=7);

  • 动态分区 (分区:提高查询性能)

    set hive.exec.dynamic.partition=true;
    set hive.exec.dynamic.partition.mode=nonstrict;

    insert into students partition(sex) select 1,‘zs’,‘m’ as sex;

  • 分桶 (按照分桶字段的哈希值取模除以分桶的个数) 理解为文件

    好处:1 方便取样 2 提高join查询效率

    创建表 clustered by (dept) into 3 buckets 按字段分桶 此字段在表中存在

    set hive.enforce.bucketing=true; //让hive强制分桶,自动按照分桶表的bucket 进行分桶。

    添加数据自动分桶

    基于桶的抽样:select * from table_name tablesmple(bucket 1 out of 3 on xx);

    -------------------取样并不是一个精确的操作,因此这个 比例不一定要是桶数的整数倍---------------------

  • 视图 相当于索引)创建视图create view view_name as select xxx ; 删除 drop view xxx;

    create view vw_customer_details as
    base64(binary(last_name)) as last_name ,
    //select unbase64(base64(binary(store_name))) from ext_store_details base64解码
    MD5(credit_no) as credit_no
    from ext_customer_details

  • 侧视图–lateral view 意义:配合explode ,一个语句生成把单行数据拆解成多行后的数据结果集 。

  • explode 作用是处理map结构的字段还有array字段也可以

    SELECT explode(array(10,20));
    select explode(map('A','Apple','O','Orange'));
    

    行转列

    select name,myscore from xx lateral view explode(split(score,’,’)) x as myscore;

    select split(score,’,’) from xx;字符串分割为数组

    列转行

    select id,
    max(if(course='a ',1,0))a,
    max(if(course='b ',1,0))b,
    max(if(course='c ',1,0))c,
    max(if(course='d ',1,0))d,
    max(if(course='e ',1,0))e,
    max(if(course='f ',1,0))f
    from t_course group by id;
    
  • hive常用函数:

    • unix_timestamp() 获取当前的时间戳
    • from_unixtime(bigint,format_str) 将时间戳转为format格式指定格式
    • datediff(string enddate,string startdate)计算两个日期相差的天数
    • current_date 获取当前日期
    • select month(string date) 返回日期中的月 此外还可以将month 换成 year ,day ,hour ,minute , second,weekofyear(返回日期当前的周数)
    • 返回星期几:

    select if(pmod(datediff(current_date, '1920-01-01') - 3, 7)='0',7,pmod(datediff(current_date, '1920-01-01') - 3, 7));

  • cast(xx as xx) 转换字段类型

  • coalesce 相当于mysql中 ifnull

    ==select nvl(null,1) 如果null是具体的数就返回具体的数。

    insert into xx select name,coalesce(chinese,0),coalesce(math,0),coalesce(english,0) from sss

    --------------------------------先更改配置文件---------------------创建内部事务分桶表----------------------------

    插入操作------>更新操作
    
  • INPUT__FILE__NAME:Mapper Task的输入文件名称

  • BLOCK__OFFSET__INSIDE__FILE:当前全局文件位置

  • select b.userid,if(trantype=1,tranmoney,-tranmoney) from bankcards b;

  • select * from userinfos u where not exists(select b.userid from bankcards b )where u.userid=b.userid group by b.userid); 不存在也要内外关联 在hive中没有not in

  • insert overwrite table table_name select xxx; 加载数据

  • 数据倾斜情况以及解决

    数据倾斜:数据的分散度不够,数据集中在一台或者几台计算机上计算,计算时间远超过平均计算速度,导致整个计算过程过慢。

    hive 中数据倾斜,一般都发生在sql中group和on上,而且数据逻辑绑定比较深。

    解决思路:调节参数和调节sql语句

    1.当遇到大小表关联时:
    在hadoop中可以通过将小表加载到缓存 这种方式就是mapjoin方式
    在hive中可以设置 mapjoin set hive.auto.convert.join=true 阈值25M


    2.部分数据相对特别少
    在mapreduce中 partition 部分自定义哈希
    在hive中partition 自定义分区

    3.当遇到很多小数据表时:
    hive中带来很多的参数和机制来调节数据倾斜
    set mapred.max.split.size=100000000;
    set mapred.min.split.size=100000000;
    set mapred.min.split.size.per.node=100000000;
    set mapred.min.split.size.per.rack=100000000;
    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

  • order by排序 对全局数据进行排序,只有一个reduce工作,速度慢

    select * from offers order by case when offerid = 1 then 1 else 0 end;

  • sort by

    sort by 只能保证对每个reduce里的字段有序。 可以指定reduce个数 set mapred.reduce.tasks=n 来指定,对输出的数据再执行归并排序。

  • distribute by

    distribute by 类似于sql中的group by 确保具有匹配列值的行被分区到相同的reducer,不会对每个reducer的输出进行排序。是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。

    SELECT department_id , name, employee_id, evaluation_scoreFROM employee_hr DISTRIBUTE BY department_id SORT BY evaluation_score DESC;

  • cluster by

    除了distribute by的功能外,还会对改字段进行排序,所以cluster by = distribute by +sort by 可以理解为分区在对指定字段排序

  • Hive 聚合

    • group by
    • Having :对GROUP BY聚合结果的条件过滤
  • 基础聚合 :

    • 使用内置函数进行数据聚合 比如:max(distinct col)、avg(distinct col)等

      select count(null) = 0

      count(*)    所有值不全为NULL时,加1操作
      count(1)    不管有没有值,只要有这条记录,值就加1
      count(col)  col列里面的值为null,值不会加1,这个列里面的值不为NULL,才加1
      
  • 高级聚合

    • grouping sets 实现对同一数据集进行多重GROUP BY操作

      SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b GROUPING SETS ( (a, b), a, b, ( ) )

    • GROUP BY WITH CUBE|ROLLUP

      cube:对分组列进行所有可能组合的聚合

  • collect_set 和collect_list函数(数据进行关联聚合,多行多列转换为单行单列)

    • collect_set 和collect_list 函数的区别:set会去重

    • select 重复的多列字段,collect_set/list(需要被形成单列的字段) ps这边结果会为数组 from 表 group by 重复的多列字段 可通过下表如[0] 来获取数组的第几列值,若超出范围会为NULL

    • concat/concat_ws函数(按指定格式合并分组内全部记录)

    • 直接用concat函数,concat后面的参数后面可以是多列,如果其中某一列为NULL,那么合并结果也为NULL

    • concat_ws 函数第一个参数为指定合并分隔符,后面的参数可以是多列,有NUll值无影响

      select month,day,concat_ws(',',collect_list(cookieid)) cw from test2 group by month,day
      
    • explde函数 只能是数组或者map类型

    • map字段进行explode 取别名要取两个as(a,b) 因为explode后会变成两列

    • 直接在select 后面用explode使用时,不能加其他字段,不能嵌套,不能groupby/cluster by/sort by

    • 为什么通常与lateral view一起出现?

      Lateral View通常和UDTF一起出现,为了解决UDTF不允许在select字段的问题

      select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable(虚拟表名) as col1, col2(map字段的列别名);
      

  • split(str,‘分隔符’) 分割后形成数组

  • substr 和substring的用法一样,substring(string A,int start,int len)

    • substr(‘abcd’,2) 截取字符串,第一个下标是1,所以返回结果是bcd
  • 窗口函数

    • 在什么情况下使用?

      用于分区排序,动态group By Top N 累计计算 层次查询

    row_number 会生成一列连续的序号,rank()函数出现1 1 3 dense_rank()则出现1 1 2这样的序号

    lag是迟滞的意思,也就是对某一列进行往后几行,lead是对某一列提前几行

    求出每个页面访问量的top2
    select username,dept,score, row_number() over() from userinfos order by dept,score
    elect page,createtime,pv,
    row_number() over(partition by page order by pv) as rn 
    where rn<3;
    
    按层次查询,如一年中,统计出工资前1/4之的部门信息,使用NTILE分析函数,把所有工资分为4份,为1的哪一份就是我们想要的结果:
    
    select deptid,sum(salary),ntile(4) over (order by sum(salary) desc nulls last) til_col from employee group by deptid;
    
    注意:order by 时,desc NULL 值排在首位,ASC时NULL值排在末尾,可以通过NULLS LAST、NULLS FIRST 控制
    
     分组后的数据标上序号。
    select userid,username,dept,score,row_number() over(partition by dept order by score) from userinfos
    
    计算累计和:统计1-12月的累积销量,即1月为1月份的值,2月为1-2月份值的和,3月为123月份的和,12月为1-12月份值的和
    
    SELECT  month,SUM(amount) month_amount,  SUM( SUM(amount)) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENTROW) AS cumulative_amount  FROM table_name  GROUP BY month  ORDER BY month; 
    注:SUM( SUM(amount)) 内部的SUM(amount)为需要累加的值,在上述可以换为 month_amount
    计算前三个月之间的和
    SUM( SUM(amount)) OVER (ORDER BY month 3 PRECENDING) AS cumulative_amount 
    

    在使用 row_number() over()函数时候,over()里头的分组以及排序的执行晚于 where group by order by 的执行。 如果没有分组hive随机分组而不是默认为1

  • 行窗口和范围窗口

  • UDF函数

    maven导入jar包-------------hive-common和 hive-exec 以及hadoop的common

继承UDF类 创建evaluate方法
public class SayHello extends UDF {
    public String evaluate(String msg){
        return "Hello,"+msg;
    }
}
打成jar包 上传到hdfs
创建UDF函数 create [temporary] function [functino_name] as 'class_path' using jar 'hdfs:///xxx/xx.jar'
调用 select funcname("传参")
  • GenericUDF(GDF)
public class SearchArray extends GenericUDF {
    //准备三个工具
    private ListObjectInspector array;
    private ObjectInspector singleEle;
    private ObjectInspector second;
  private IntWritable result=new IntWritable(-1);

    /**
     * 设置本函数的返回值类型
     * @param
     * @return
     * @throws UDFArgumentException
     */
    @Override
    public ObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
       //对第一个参数强转成集合
        array =(ListObjectInspector) args[0];
        //获得集合中单个元素
        singleEle = array.getListElementObjectInspector();
        //获得第二个参数
        second = args[1];
        return PrimitiveObjectInspectorFactory.writableIntObjectInspector;
    }

    @Override
    public Object evaluate(DeferredObject[] args) throws HiveException {
    this.result.set(-1);
    Object arr = args[0].get();
    Object val = args[1].get();
    int len = array.getListLength(arr);
        for (int i = 0; i < len; i++) {
           Object ele= array.getListElement(arr,i);
           if (ele!=null){
               if (ObjectInspectorUtils.compare(val,second,ele,singleEle)==0){
                       this.result.set(1);
                   break;
               }
           }
        }
        return result;
    }
    //说明文件
    @Override
    public String getDisplayString(String[] strings) {
        return null;
    }
}

你可能感兴趣的:(hadoop)