Hive学习一

作者: 大石兄 | 来源:发表于2018-12-30 11:35 被阅读9次

    vi命令:

    ctrl + :切换到命令模式,输入 %s/a/b/g ,会将 a 替换成 b。
    
    vi 编辑后文件,如果错误地使用 ctrl +zz 关闭编辑,下一次打开时会老是报错。这是因为这样并没有退出编辑文件,可以通过杀死进程来解决
    

    注意直接杀死进程是不行的,因为会有一个临时文件

    ps aux | grep vi (或者 ps -ef | grep vi) ,kill -9 6087 ,但是不行。

    正确方法,删除 .xx.txt.swp 临时文件

    ll 显示文件后,然后 rm .xx.txt.swp

    删除全部内容:
    
    在命令模式下 ,先使用 :0或:1 跳到文件第一行,然后输入:.,$d(表示删除当前光标后面的所有内容) 一回车就全没了
    

    另::$ 跳到文件最后一行

    hive 的基本使用介绍

    1、hive 的参数设置方式

    a、直接在 hive 窗口使用 set 去设置:只对当前连接的 session 有效

    让提示符显示当前库,这样结果就会显示当前所在库名了。

    设置 hve命令 打印当前的库

    set hive.cli.print.current.db=true;

    显示查询结果时显示字段名,不设置使用 select * from table ,只会有数据,不会有对应字段提示。

    set hive.cli.print.header=true

    [图片上传失败...(image-d503ab-1546140371812)]

    注:上面两个参数设置都只是临时的,如果关闭 hive 将会失效

    解决办法:

    在 linux 的当前用户目录下(即~,cd 命令下),编辑一个 .hiverc 文件(隐藏文件,hive启动时会去加载这个文件),写入以下参数
    

    set hive.cli.print.current.db=true;

    set hive.cli.print.header=true;

    b、配置文件设置:全局有效

    用户自定义配置文件:$HIVE_CONF_DIR/hive-site.xml

    默认设置文件:$HIVE_CONF_DIR/hive-default.xml

    注:使用 vi ~/.bashrh 命令查看设置的各个全局变量,知道 hive、hadoop 的安装目录是在哪里

       使用 vi /etc/hosts 查看 ip 地址的别名
    

    [图片上传失败...(image-a4b758-1546140371812)]

    c、启动hive 窗口或者远程连接时指定:只当前session 有效

    使用以下命令启动,设置显示当前库名,可以跟多条参数

    hive -hiveconf hive.cli.print.current.db=true hive.cli.print.header=true

    3、启动 hive 的另一种方式:把 hive 启动为一个服务(端口10000),这样就可以使用 hive客户端(beeline)在任意地方访问了。

    启动服务端,注意这是阻塞式的,输入以下命令

    /opt/hive2.1/bin/hiveserver2

    注意:在后台运行的启动方式,1表示标准输出信息>重定向输出,2表示错误信息,最后一个&就是表示不阻塞后台运行,这里指向 /dec/null 是一个黑洞,放什么都会消失。加nohup 是为了不会因为当前用户退出而导致服务退出,而是会一直运行除非使用 kill -9 杀进程,jobs -l 命令可以查看进程号, 或者使用ps aux|grep file.name

    nohup /opt/hive2.1/bin/hiveserver2 1>/dev/null 2>&1 &

    可以使用命令查看 10000 端口,有看到10000端口这样就可以启动客户端

    netstat -nltp

    启动客户端,这是一个交互式程序

    /opt/hive2.1/beeline

    写命令连接到服务端,URI 符合jdbc规范,用户是启动 hdfs 的用户名

    !connect jdbc:hive2://192.168.109.147:10000:用户名:密码

    服务端连接成功后,就可以写 hive 命令了

    select * from table

    客户端关闭

    !quit

    总结:

    使用这种方式连接会和 mysql 的显示一样很好看,服务端会显示客户端的执行结果
    
    注意程序是在开启服务端的机器运行的,下面分区表中是从本地加载文件到 hdfs,如果文件是在客户端的,那么 load data local inpath 语句将会报错;'文件不存在'。此时就需要在文件所在机器直接用 hive 命令开启而不是用客户端连接了,这样就可以了。
    

    4、hive 的脚本运行方式:不会进入hive 命令行

    注意这个是 linux 命令,而不是在 hive 里面敲的,etl.sh 脚本如下

    hive -e 'show databases;

    select * from cookie4'

    所以利用上面这个原理,就可以把很多命令都写成 hive -e 的形式,组成一个脚本 et1.sh,然后使用 sh et1.sh 命令执行 shell 脚本,可以把所有要执行的hive 语句都放到一个 hive -e "*****"; 里面, 使用hive -v -e “***” 会输出日志信息

    [图片上传失败...(image-ef0edd-1546140371812)]

    5、hive 命令的另一种执行方式:不会进入hive 命令行

    适用于命令很长,用脚本也不不好写(一条语句几百行),就可以将命令写到一个 *.hql 文件(有; ,上面脚本的没有 ;),然后执行

    hive -f test.hql

    文件内容如下

    select * from cookie5;

    6、运行一个参数文件,从配置文件中启动 hive,并加载配置文件中的参数:会进入hive 命令行

    inithive.conf 的内容如下,里面也可以放一下 hql 执行语句

    use myhive;

    set hive.cli.print.current.db=true;

    一、hive的语句

    查看当前所在库

    select current_database();

    模糊查找表名:包含lan 的表

    show tables 'lan';

    查看表信息

    desc formatted table_name; 排列友好

    desc extended table _name;

    show create table table_name;

    1、建库

    建好库后,就会在 hdfs 中生成目录:/opt/hive2.1_data/warehouse/db_order.db

    create database db_order;

    建带属性的库:

    create database db_name comment '库的属性:可选' dbproperties('creater'='lanyi','date'='2018-11-02')

    删除库:

    drop database db_lan; 空库

    drop database db_lan cascade; 不是空库,库里面有表

    2、建表

    标准,包含 数组、结构体、字典的建表语句

    create table cdt(

    id int comment '识别码',

    name string comment '姓名',

    work_location array<string>,

    piaofang map<string,bigint>,

    address struct<location:string,zipcode:int,phone:string,value:int>)

    row format delimited fields terminated by '\t'

    collection items terminated by ','

    map keys terminated by ':'

    lines terminated by '\n' (默认就是以换行区分一条记录,可以省略)

    stored as textfile; (默认文件格式)

    使用 show create table cdt; 命令可以得到

    表示是以\n 区分每行记录

    ROW FORMAT SERDE

    'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'

    表示底层文件存储格式是 textFile

    STORED AS INPUTFORMAT

    'org.apache.hadoop.mapred.TextInputFormat'

    OUTPUTFORMAT

    'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

    注意:Hive 对文件中字段的分隔符默认情况下只支持单字节分隔符,如果数据文件中的分隔符是多 字符的,如下所示:

    01||huangbo

    02||xuzheng

    03||wangbaoqiang

    但是可以使用RegexSerDe 正则表达式来解析实现双字节分隔符

    create table t_bi_reg(id string,name string)

    row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'

    with serdeproperties('input.regex'='(.)\|\|(.)','output.format.string'='%1s %2s')

    stored as textfile;

    load data local inpath '/home/hadoop/data.txt' into table t_bi_reg;

    表建好后,会在库目录下再建一个表目录, /opt/hive2.1_data/warehouse/db_order.db /t_order

    注意,如果不写 row 后面的语句,hive 会认为表数据文件中的字段分隔符为 ^A,这是一个

    create table t_order(id string,create_time string,amount float,uid string) row format delimited fields terminated by ',';

    表建好后,可以尝试把数据放到 hdfs 下,数据要放到表目录中。如

    建立一个表

    create table t_movie(movie string,actor string) row format delimited fields terminated by ',';

    数据文件为 movie.dat,内容如下(一行一条数据,以逗号分隔)

    zhuilong,liudehua

    tianyi,

    sansheng,wangfei

    把数据放到 hdfs 文件目录,注意是表目录下

    hadoop fs -put ./movie.dat /opt/hive2.1_data/warehouse/db_order.db/t_movie

    通过 子查询建表,会带有查询出来的数据

    create table t_data

    as

    select *****;

    注意:这种查询建表的方式生成的表字段名,会是查询结果的字段名,如果使用了 nvl(非空字段时取值,空字段时取值)这种不确定字段名的情况,就要使用 as 取别名,不然会又异常。

    上面的注意情况,如果是查询数据插入到表中,则不用关注别名问题,因为不管取不取名字,插入表都是已经有字段名字了。

    增加字段:

    alter table t_date add columns (score int comment '得分',address string comment '地址')

    增加分区:是增加分区,而不是增加分区字段

    alter table t_date add partition(city = 'shenzhen');

    alter table t_date add partition(city='ganzhou') partition(city='nankang');

    3、删除表

    hive 会从元数据库中清除关于这个表的信息,还会从 hdfs 中删除这个表的表目录

    drop table t_order;。

    删除表中数据,清空数据

    truncate table tablename

    删除库:

    drop database db_lan; 空库

    drop database db_lan cascade; 不是空库,库里面有表

    删除分区,注意要有引号,因为分区字段定义是string

    ALTER TABLE my_partition_test_table DROP IF EXISTS PARTITION (y=“2018 ”,m=“08”;

    删除字段:不支持,但是可以使用 replace columns 替换字段来实现

    删除分区:

    alter table t_data drop partition (city='shenzhen');

    3.1、改表

    修改字段: 会将 name 字段变成 new_name sring类型,如果有注释仍然保留,不影响表数据

    alter table t_data change name new_name string;

    修改(替换)所有字段:会依次把字段替换掉,表数据保留并一 一对应,如果字段变少数据也变少,变多则为null。用来替换所有字段

    alter table t_date replace columns (id int , name string , address string);

    修改分区:只能修改分区存储的位置

    此时原先的分区文件夹仍存在,但是在往分区添加数据时,只会添加到新的分区目录

    alter table student_ptn partition (city='beijing') set location '/student_ptn_beijing';

    添加分区时就指定分区的存储目录

    alter table student_ptn add if not exists partition(city='beijing')

    location '/student_ptn_beijing' partition(city='cc') location '/student_cc';

    4、内部表 Managed_table 和外部表 External_table

    建外部表的语法:不指定目录的就是 内部表

    a、内部表的目录在 hive 的仓库目录中(/opt/hive2.1_data/warehouse ),外部表的目录由用户指定

    b、drop 一个内部表时:hive 会清除相关元数据,并删除表数据目录(数据也没了)

    c、drop 一个外表表时:hive 只会清除相关元数据(数据还在)

    eg:

    在 hdfs 下建立两级目录,所以带上了 -p,

    hadoop fs -mkdir -p /pvlog/2017/

    将造的日志数据 pv.log 放到 hdfs 新目录下(暴力导入数据),数据如下图

    hadoop fs -put pv.log /pvlog/2017/

    [图片上传失败...(image-9e70a0-1546140371812)]

    建立外部表,将数据和表关联到一起(这样就不用将数据移动到表目录了)

    create external table t_access( ip string,url string, access_time string ) row format delimited fields terminated by ',' location 'access/log';

    此时查询数据,可得下图

    select * from t_access

    [图片上传失败...(image-899bbf-1546140371809)]

    5、分区表

    在表目录中为数据文件创建分区子目录,以便于在查询时,MR 程序可以针对分区子目录中的数据进行处理,缩减读取数据的范围(不然就要全部读取)。

    比如:网站每天产生的浏览记录,浏览记录应该建一个表来存放,但是,有时候,我们可能只需要对某一天的浏览记录进行分析,这时,就可以将这个表建为分区表,每天的数据导入其中的一个分区,当然,每日的分区目录,应该有一个目录名(分区字段)。

    partitioned by(day string)就是分区的依据

    下面是建表语句,只会建表目录,分区的目录是在放数据的时候建立,先建表再放数据

    create table t_pv_log(ip string,url string,comit_time string)partitioned by(day string)row format delimited fields terminated by ',';

    创建两个日志数据文件,分别是 pv15.log,pv16.log 表示15、16两日的日志信息,然后导入数据。

    将数据导入分区表,local表示从本地目录,partition 表示当前数据是哪个区的。

    注意要保证运行此命令的机器与文件所在机器是同一台,不然会报文件不存在错误,此问题针对于服务器、客户端方式启动 hive 的情况。

    load data local inpath '/home/python/Desktop/pv15.log' into table t_pv_log partition(day='0615');

    导入数据后在表目录下会创建一个目录 day=0615,里面存放着 pv15.log 文件

    也可以查询到数据了,结果如下图(多了一个字段)

    select * from t_pv_log

    [图片上传失败...(image-21279f-1546140371812)]

    查询不同区的数据

    select * from t_pv_log where day=‘0615’;

    注意:这里各个区的数据文件名字是无关紧要的,不同区的名字也可以相同,只看用户是将什么数据导入了什么区去。

    另外因为分区会多一个字段,所以要注意不能是表中已有字段名
    

    查询分区

    show partiticons tablename;

    6、CTAS 建表语法

    通过已存在的表来建表

    创建一个和 table1 一样字段的 table2 表

    create table table2 like table1

    创建一个表类似与已有表,不仅字段一样而且还带有数据(好像不会有分区),查出来是什么字段名新表就是什么字段名

    create table table2

    as

    select * from table1 where ip>‘192.168.109.2’;

    7、将数据导入 hive 表

    方法1:手动用 hdfs 命令,将文件放到表目录下

    方法2:从linux本地导入 文件,在 hive 的交互式 shell 中用 hive 命令来导入本地数据(非hdfs)到表目录,本地文件还在,并且表目录下也会有一份数据

    这是 hive 命令:注意表的文件类型是 textfile 才可以导入 txt等文本文件

    load data local inpath ‘/root/order.data’into table t_order;

    方法3:从hdfs 系统导入文件,用 hive 命令导入 hdfs 中的数据到表目录(命令没有 local)

    注意从 hdfs 中导入文件,文件会被移动到表目录下

    这是 hive 命令

    load data inpath ‘/opt/order.data’ into table t_order;

    方法4:直接插入数据,和mysql一样

    [table] 可以省略,注意

    insert into [table] tablename [partition(y=,m=,d=*)] values(字段1值,字段2值,...) ,(字段1值,字段2值,...) ,,,

    insert into [table] tablename (字段1,字段2,...) values (字段1值,字段2值,...),,,

    会重写数据

    insert overwrite table table_name 【partition(y=2018’,m=08)】

    select * from 。。。

    会插入数据,注意插入语句要保证数据与字段是能匹配的,不然报错

    insert into table table_name【partition(y=2018’,m=08) 】

    select * from 。。。

    视图:

    和关系型数据库有差别

    a、只有逻辑视图,没有物化视图

    b、视图只能查询,不能load、insert、update、Delete数据

    c、视图再创建的时候,只是保存了一份元数据,当查询视图的时候,才开始执行视图对应的那些子查询

    不手动指定视图的字段信息

    cretate view view_name as select * from cdt;

    创建视图的时候加上表注释

    create view view_name(name comment '姓名',age comment '年龄')

    comment '这是视图注释,可省略'

    as select * from cdt;

    二、Hive 的关联查询

    1、内连接 ,join 或者 inner join

    没有连接条件,结果会是 t_a、t_b两个表的所有行两两相连接

    这种就是叫 笛卡尔积

    select a.* ,b.* from t_a a join t_b b ;

    有连接条件的连接语句,求交集,是inner join

    select a.* ,b.* from t_a a join t_b b on a.name=b.name;

    [图片上传失败...(image-9ac445-1546140371811)]

    2、左连接, left join 和 left outer join是一样的

    以左边为基准,左边表数据都保留,右表如果没有符合连接条件的会显示 NULL

    select a.* ,b.* from t_a a left join t_b b on a.name=b.name;

    [图片上传失败...(image-faa969-1546140371811)]

    右连接,类似

    [图片上传失败...(image-bfbb26-1546140371811)]

    3、全外连接,full outer join

    左右表的数据都返回,哪个表没有就补充 NULL,不是join

    select a.* ,b.* from t_a a full outer join t_b b on a.name=b.name;

    [图片上传失败...(image-356c2f-1546140371811)]

    4、左半连接,semi join

    右表数据不返回,左表数据只返回连接上的,类似 inner join 结果的一半

    注意 select 结果不能有 b 表的东西,因为查出来就没有结果

    select a.* from t_a a semi join t_b b on a.name=b.name;

    [图片上传失败...(image-1b6c58-1546140371811)]

    5、lateral view 连接:(这个一般意义上不叫连接)

    可以把表扩展一些新的字段,但是后面需要连接数组(hive里面的数据类型array)、列表(tuple,使用 json_tuple 函数处理json字典数据时的结果),表扩展的对应行数据扩展后会对应行拼接起来

    json 是表名,data 字段存放的是json 数据

    select * from json lateral view json_tuple(data,'movie','rate','timeStamp','uid') a as a1,a2,a3,a4;

    [图片上传失败...(image-fc29d0-1546140371811)]

    [图片上传失败...(image-d597b7-1546140371811)]

    [图片上传失败...(image-c4531a-1546140371811)]

    三、分组聚合

    一些函数

    hive 中使用 show functions 可以查看函数命令

    1、大写函数

    将 url 字段内容大写

    select upper(url)from t_pv_log;

    [图片上传失败...(image-8c52d6-1546140371811)]

    2、计数、count

    3、查看分区

    show partitions t_table;

    求每条 url 的访问总次数

    分组的表达式是对分组的数据进行逐组运算

    count(1)表示一行就加一个

    select url ,count(1) from t_pv_log group by url;

    group by 分组后排序,使用 order by

    这个是错的:会报 chn_name 字段不存在,这是因为order by 是对查询出来后的结果进行排序,必须是查询出来有的字段名

    select length(chn_name),count(1) from tmp_base_info group by length(chn_name) order by length(chn_name);

    下面这个才是对的:

    select length(chn_name) as chn,count(1) from tmp_base_info group by length(chn_name) order by chn;

    注意:分组查询的结果,只有分组条件字段可以直接写,其他字段只能是聚合函数的结果

    四、子查询

    把查询结果当做是一个表,用括号包起来并取一个别名,然后去查询。

    五、hive 的数据类型

    普通数据类型:

    1、tinyint、smallint、int、bigint、float、double

    2、日期类型 timestamp(时间戳)、date

    eg:

    有一些数据
    

    1,zhangsan,1985-09-08

    2,lisi,1979-07-18

    那么可以创建一个表,带 birthday date 字段的去接收这些数据

    3、string、char(字符型)

    4、boolean(值为true、false)、binary(二进制)

    复合数据类型:

    1、array 数组类型

    eg:有一个数据的一部分是 ‘吴京:杨刚:王伟’,如果将保存这个数据的字段定义为 string,那么要求获取其中一部分不太好求(要根据冒号切片),但是如果保存为数组就方便很多了。

    定义为数组,里面是string

    并且指定集合字段按照‘:’来切分

    create table t_movie(movie_name string, actors array<string>,first_show date)

    row format delimited fields terminated by ','

    collection items terminated by ‘:’;

    [图片上传失败...(image-95253e-1546140371811)]

    只取数组中一部分数据,如这里用角标取出第一个演员名字

    [图片上传失败...(image-fbe77-1546140371811)]

    配合函数可以实现更多功能:例如array_contains 查询包含某一演员的电影

    select movie_name,actors,first_show

    from t_movie

    where array_contains(actors,'吴刚');

    求电影有几个演员

    select movie_name,actors,first_show ,size(actors)

    from t_movie;

    2、map 类型

    eg:有一些数据如下,第二个字段是表示其家庭成员(可以 key 不一致)

    1,zhangsan,father:xiaoming#mother:xiaohua#brother:xiaosu,28

    2,lisi,father:mayun#mother:huangyi#sister:guanwu,22

    那么可以使用一个 map 类型来对上面数据中的家庭成员进行描述

    建表语句,map 里面放的是两个 string

    并且分别告诉字段怎么切,元素怎切,key values 怎么切

    create table t_person(id int,name string,family_members map<string,string>,age int)

    row format delimited fields terminated by ','

    collection items terminated by '#'

    map keys terminated by ':';

    查询结果

    select * from t_person

    [图片上传失败...(image-7d2048-1546140371811)]

    查询每个人的爸爸,使用字典的取值方式

    select id,name,family_members【'father'】,age

    from t_person;

    [图片上传失败...(image-7af6fc-1546140371811)]

    查出每个人有哪些亲属,只需要取 map 的 key

    select id,name,map_keys(family_members)as relations

    from t_family;

    [图片上传失败...(image-edab34-1546140371811)]

    查出每个人亲属的名字,只需要取 values

    select id,name,map_values(family_members)as relations

    from t_family;

    [图片上传失败...(image-dc098f-1546140371811)]

    查出每个人的亲人数量

    select id,name,size(family_members)as relations

    from t_family;

    查出所有拥有兄弟的人

    这里用了函数的嵌套,使用了数组判断元素的函数

    select id,name,age from t_person

    where array_contains(map_keys(family_members),‘brother’);

    或者用子查询来实现

    select id,name,age

    from (select id,name,age,map_keys(family_members)as relations)tmp

    where array_contains(relations,‘brother’);

    [图片上传失败...(image-875979-1546140371811)]

    3、struct 结构体类型:

    是类与 对象的结构,就是 c 语言里面的对象,因此用点语法

    eg:有以下数据

    1,zhansan,18:male:深圳

    2,lisi,28:female:北京

    3,wangwu,38:male:广州

    4,赵六,26:male:上海

    5,钱琪,35:male:杭州

    6,王八,48:female:南京

    建表映射上面的数据,因为数据结合在一起所以用结构类型来表示

    防止表存在,存在就删除,不存在不会影响

    drop table [if exists] t_user

    create table t_user(id int,name string,

    info struct<age:int,sex:string,addr:string>)

    row format delimited fields terminated by ','

    collection items terminated by ':';(导入数据的时候结构体用:来分隔)

    [图片上传失败...(image-a3d960-1546140371810)]

    查询每个人的 id,地址,取数据用点语法

    select id,name,info.addr from t_user;

    [图片上传失败...(image-83696a-1546140371810)]

    相关文章

      网友评论

        本文标题:Hive学习一

        本文链接:https://www.haomeiwen.com/subject/rqcvlqtx.html