hive(I)--学习总结之常用技能

  hive是Apache的一个顶级项目,由facebook团队开发,基于java开发面向分析师或BI等人员的数据工具(常用作数据仓库),它将hdfs文件组织成表,使用hive-sql调用mapreduce任务完成计算。即使你不知道它的内部机制也不懂java,却不影响你使用。

  这里主要以CLI使用为主,材料来源《Hive权威指南》、个人工作和网上讨论。在阅读前,希望可以先了解一下hive的安装(上一篇博客有),这对理解hive的运行机制有一定帮助。如有疑问或问题,欢迎沟通讨论。

 

shell执行hive

  hive命令在shell中执行有多种,可以通过hive --help --service cli进行查询具体参数,使用如下 

1 #执行SQL语句
2 hive -e "sql语句"  #可以添加-S参数,设置静默状态,不输出ok等消息
3 
4 #执行SQL文件
5 hive -f sql_file (或者加载hive -S -f sql_file  注:S-Silence)
6 
7 #执行SQL文件并留在hive交互窗口
8 hive -i sql_file

 

hive中用(hadoop) shell命令

  >当我们进入hive的交互模式后,不需要像shell(hadoop fs -cmd -para dir/file)那样与hadoop文件交互,使用dfs就可以了。

    例如:当我们想看看一张表的大小时,我们首先找到这张表的位置(假设我们用desc formatted table_name我找到对应表的location)

     hive > dfs -du -s -h hdfs://usr/hive/warehouse/mydb.db/tab2

  >当我们需要执行一个hive文件时,可以使用source关键字.

    例如:hive> source /home/shj/sql_file.sql;

  >当我们希望执行一个shell之后而又不想退出hive时,可以在命令前后添加"!"和";"就可以了。

    例如:hive > ! ls /home/shj/ ;

 

hive中的表

  hive通过metastore实现与文件的映射。hive中的数据库其实是一个目录(该目录我们可在hive-site.xml中设置hive.metastore.warehouser.dir,假设该值我们设置为/usr/hive/warehouse,那么后期创建的数据库都是该目录的子目录),以db格式的文件。比如说我create database mydb;那么这个数据库文件就是:/usr/hive/warehouse/mydb.db,后期建的表对应文件是这个目录的子文件。

  I、hive表类型:管理表(内部表)、外部表、分区表(静态、动态)、分桶表。  (不同维度的划分)

    >内部表:我们正常建立的表属于内部表,hive管理着这个表(元数据和文件数据),我们操作该表就是操作该元数据以及文件数据。要是我们删了这个表,也就是删了这个表对应的文件

    >外部表(external):外部表类似于将hive与文件的链接(link),hive仅管理着元数据。当我们删除该表时,也只是删除数据结构,底层文件并没有被删除。

    >分区表(partition):当数据量比较大,进行查询时必然导致性能问题。而分区表,就是对大量的表文件以一个虚拟列(如地区、时间)的方式进行拆分成多个文件。指定分区进行查询时,仅扫描对应分区文件,有效提升查询性能。(查询时应指定,在不确定分区范围时将进行全分区扫描,性能差)

    >分桶表(bucket):工作中遇到的不多,会用来进行数据抽样(tablesample其实也可以用,此外两个分桶表join进行查询时效率会提升很多)。它与分区表的不同,它分桶的列是表中真实存在的列。文件组织分式与分区相似。

  II、查看表信息

    当一个表已经创建好了,我们怎么看这个表呢?(它的字段,备注,创建人,基本统计信息,文件地址等等)

    >desc [extended/formatted] mydb.tab2; desc是describe的缩写,当我们查看表时补充上extended或formatted时输出的信息将更多。推荐使用formatted,这样输出的信息相对标准化,更容易找到我们要的信息。这些信息中,Table Type如果是"MANAGED_TABLE"是内部表,"EXTERNAL_TABLE"是外部表;分区和分桶信息可以参见:Partition Infomation和Number Buckets

    >show tables  in mydb like '*tab1*';查询在mydb库中,关键字“tab1”的表名称。(这里非%)

    >set hive.cli.print.current.db=true;set hive.cli.print.header=true;第一个:显示当前库名;第二个:输出列名;

  III、hive表的创建

     创建或修改或删除都可以在语句中添加if判断来避免系统报错(if [not] exists),文章中不再说明这点。在表的创建中,我们除了指定分隔符,还可以指定表备注(COMMENT)、表属性(TBLPROPERTIES)、指定文件地址(LOCATION)等。如果想复制他表结构:create table mydb.tab2 like mydb.tab_tmp;

    >内部表:create table mydb.tab2(col1 string,col2 int,col3 bigint,...)row format delimited fields terminated by '\001' stored as textfile;(存储格式不指定时,默认以textfile;)

    >外部表:create external table mydb.tab2(col1 string,col2 int,col3 bigint,...) row format delimited fields terminated by '\001' location ‘/other/data’;(创建时便指定加载)

    >分区表:create table mydb.tab2(col1 string,...) partitioned by (year string,month string) row format delimited fields terminated by '\t';

    >分桶表:create table mydb.tab2(col1 string,...) clustered by (type) into 10 buckets row format delimited fields terminated by ',';(这里其实还需要配置一些参数,暂略)

    数据创建时,默认存储格式textfile;此外,常用的还有orcfile(通过对行记录块进行列存储并压缩,每个块提供一个存储),相比于textfile而言,对于大数据量,orcfile写入较慢,但查询和空间都比textfile更好(写入时需要启动解压缩)。下面的列表是对150万的数据进行的比照。很明显大数据量下orcfile对查询和磁盘占用更加友好。【补充:并不是所有的查询都会比textfile快】

    

   IV、hive表的修改

    >修改表名:alter table mydb.tab3 rename to mydb.tab2; 

    >修改列:alter table mydb.tab2 change column col_old col_new bigint [comment'修改示例'] after other_col;

    >增加列:alter table mydb.tab2 add columns(col1 string ,col2 int.col3 bigint);

    >删除列:alter table mydb.tab2 replace columns (var1 int comment '***'  ,var2 bigint comment '***',.....)   仅保留这些字段,其他字段都将被删除

    >增减分区:alter table mydb.tab2 add(/drop) if [not] exists partition(year='17',month='02') [....] ;

  V、数据导入/导出hive

    >数据导入

      load data [local] inpath '/test/hive/data/' [overwrite] into table mydb.tab2 [partition (year='201709')];

      说明:local参数指示为本地文件,无则为hdfs文件。overwrite是否为覆盖原有【分区】数据,partition为指定分区;

        hive > load data local inpath '/home/shj/data/' into table mydb.tab_tmp;(说明,路径最好就是一个文件夹,hive将加载文件下的所有数据;对应的加载表应该已创建)

        hive > load data inpath '/hive/warehouse/data/input/' into table mydb.tab_tmp_1 partition(year='2017');(hdfs中数据就move了,不同于本地的复制;注意inpath文件夹下不能含有文件夹)

      除了load,还可以使用查询语句导入数据(hdfs)

        hive > insert into mydb.tab2 select * from mydb.tab_tmp where conditions;

        hive > create table mydb.tab2 as select * from mydb.tab_tmp where conditions;

    >数据导出

      insert overwrite [local] directory '/hive/data'  select * from mydb.tab2 where conditions;(指定local则为本地文件,directory后面后文件夹,如果没有对应路径,会自动创建)

        hive >  insert overwrite directory 'home/shj/data/export/' select * from mydb.tab2 where conditions;(导出到本地,默认列分割符为'\t'。建表时的分隔符被取代)

        hive > insert overwrite directory '/cluster/hive/warehouse/mydb.db/test/' select * from mydb.tab2 where conditions;(导出到hdfs,列分割符默认是'\001'即^A)

        此外,常用的还是用hive -e/f > /directory/filename进行数据的导出。

hive中的查询

    hql与t-sql还是有一定的差异的。这里我们谈谈join、排序和抽样。

    join:hive中的join是只支持等值链接。也就是a join b on a.c1=b.c1;不支持非等值连接。此外,hive中除了支持常用的left join /right join /full outer join,还有一种join类型:left semi-join(左半开链接)。用来返回左边表记录,只要记录满足与右边表的on条件,是对in/exists的一种优化。(join优化将在后面单独说明。)

      hive > select a.* from tab2 t1 left semi join tab_tmp t2 on t1.c1=t2.c1 and t1.c2=t2.c2;

    排序:hive中可实现排序有distritute by 、sort by、order by。distribute by是在map输出时以什么样的方式到reduce中(多个reduce,根据什么key);sort by 是reduce完成后,单个reduce怎么将结果进行排序;order by是全局的排序,在一个reduce中完成。当数据量大时,order by将耗时较长。可以先指定distribute by 后指定sort by。实现输出的结果根据某些字段排序。当distribute by与sort by的字段相同时,则等同于cluster by。

      hive > select * from tab2 distribute by c1,c2 sort by c1;

      hive > select * from tab2 cluster by c1;

    抽样:当数据很大时,就避免不了抽样。在hive中关键字tablesample实现,一种分桶抽样,一种数据块抽样。

      hive > select * from mydb.tab2 tablesample(bucket 12 out of 1000 on rand()) s;(分母是分桶数,分子是指定桶序号;关键字rand()保障随机性,即同样两次抽样结果不同)

      hive > select * from mydb.tab2 tablesample(0.02 percent) s;(百分比抽样,这里相当于10000中取2个)

 

hive参数调整

    hive中的参数常常用于调优,设定map/reduce数,map-join,block大小,是否本地化等等。这个我们会在后期进行探讨和沟通。现在我们看看,使用CLI端,有哪些设置让操作更加舒适

    > set hive.cli.print.header=true;设置输出是否带有表头(当我们输出文件时,没有表头可能对导入数据库和阅读带来一定影响。这个参数完美解决这个问题。)

    > set hive.cli.print.current.db=true;显示当前数据库位置(可以使用use database;进行数据库切换)

    > set hive.exec.parallel=true;允许任务并行,可以提高我们查询效率

 

未完待续!

原创博客,转载请注明出处!欢迎邮件沟通:shj8319@sina.com

posted @ 2017-09-14 15:36  999.感冒灵  阅读(988)  评论(0编辑  收藏  举报