201707061217复习-hive篇

一、

  1、首先,hive只是一个数据仓库,只是一个工具,用来映射hdfs上的文件,所以hive并没有集群模式。

      其次,hive的元数据需要一个数据库保存,内置deby数据库,不建议使用,建议使用另外的mysql数据库。所以装hive之前需要先装mysql。mysql安装步骤见"mysql安装.txt"   

   解释器、编译器、优化器、执行器 

    加载数据的过程中,不需要从用户数据格式到 Hive 定义的数据格式的转换,因此,Hive 在加载的过程中不会对数据本身进行任何修改,而只是将数据内容复制或者移动到相应的 HDFS 目录中

   因此,hive不扫描数据,也就不会针对数据建立索引。如果要建立索引,则会导致倒数数据速度下降  

 

  2、hive的数据类型:除去类似于mysql中的类型外,还有复杂类型:

    struct() 结构类型

    map()  kv类型

    array()   数组类型

  3、建表语法

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

   [(col_name data_type [COMMENT col_comment], ...)]

   [COMMENT table_comment]

   [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]

   [CLUSTERED BY (col_name, col_name, ...)

   [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]

   [ROW FORMAT row_format]

   [STORED AS file_format]

   [LOCATION hdfs_path]

 

说明:

1、 CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常

2、 EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

3、 LIKE 允许用户复制现有的表结构,但是不复制数据。

4、 ROW FORMAT

DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]

        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]

   | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive通过 SerDe 确定表的具体的列的数据。

5、 STORED AS

SEQUENCEFILE|TEXTFILE|RCFILE

如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。

6、CLUSTERED BY

对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

把表(或者分区)组织成桶(Bucket)有两个理由:

1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

  4、托管表,也叫内部表,hive完全控制,删除数据时,元数据删除,源数据也删除。

  5、外部表,更安全,删除表是只删除元数据,源数据并不删除

  6、分区表,根据某个字段分区,一个分区是一个目录

  7、桶表:将分区里的数据在partition成多个文件,如果根据hash分,那么查询时,指定到分区,指定到key,根据key到指定的小文件中查询,速度会很快,分桶表的正真作用在于减少join时的数据操作的效率:select a.id,a.name,b.addr from a join b on a.id = b.id; 如果a表和b表已经是分桶表,而且分桶的字段是id字段做这个join操作时,还需要全表做笛卡尔积吗?

  8、加载数据,使用load,或者从另一个表查询的结果导入到新的表中。

  9、常用横转竖:explode

      explode(ARRAY)  列表中的每个元素生成一行

      explode(MAP) map中每个key-value对,生成一行,key为一列,value为一列

  10、什么情况下不用mr?

    不做过多的处理,只是把数据全部加载出来而已就不使用mr程序:例如:

    不用where 子句,只是 select * from  table ;    把数据全部加载出来就行了,无需mr程序

    使用的where子句是分区字段,只需要把在hdfs上的分区目录下的文件全部加载出来就行。

  11、hive 转化为mapreduce的原理:见http://www.aboutyun.com/thread-20461-1-1.html

  12、hive的优化

    12.1、多个表join,使用相同的字段进行join

    12.2、join时从左到右的表依次要从小到大

    12.3、使用查询暗示,即手动指定让hive使用map端join,  例如:select /*+StreamTable(a)*/  a.name, b.stu_id  from student_table_small a  join student_table_big b  where b.age>=a.age 

    12.4、也可以让hive自己决定是否使用map端join,参数如下:

         set hive.auto.convert.join=true;    小表自动选择Mapjoin,  默认值:false。该参数为true时,Hive自动对左边的表统计量,若是小表就加入内存,即对小表使用Map join

       set hive.mapjoin.smalltable.filesize=25000000;   小表阀值  默认值:25M

        set hive.mapjoin.followby.gby.localtask.max.memory.usage;     map join做group by操作时,可使用多大的内存来存储数据。若数据太大则不会保存在内存里  默认值:0.55

        set hive.mapjoin.localtask.max.memory.usage;    本地任务可以使用内存的百分比 默认值:0.90

    12,5、启动严格模式 必须使用limit   hive.limit.optmize.enable = true

     12.6、并行执行 , 每个task启动多个线程来执行任务

     12.7、增加reducer的个数

     12.8、jvm重用,用于小文件或task特别多,避免jvm启动的开销

     12.9、压缩

  13、各种join

    join = inner join  : 两个表能关联上的内容才输出,

    left join = left outter join : 左表中的数据全部输出,即使在右表中没有匹配

    right join = right outter join : 右表中的数据全部输出,即使在左表没有匹配

    full outter 两张表都输出,没有匹配到的,补空

    left semi join 相当于mysql中的in语法,即select * from a where a.id in b.id     只查询左表中的数据,当a表中的id也出现在右表中时。

    ############注意点#####################

    0、只支持等值join 例如:a join b on a.id - b.id   而不支持 a join b on a.id > b.id

    1、多表join , a join b on a. id = b.id join c on b.id = c.id 两个都是哟用了b.id字段,那么只会生成一个mr程序

                          a.join b on a..id = b.id join c on b.id2 = c.id  一个是b.id,另一个是b.id2,那么会生成两个mr程序

    2、多表join时,reduer会缓存除最后一张表以外的所有表,所以为了减小内存压力,近两个将小表放在前,大表放在后,如下:

       SELECT a.val, b.val, c.val FROM a  JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)

       所有表都使用同一个 join key(使用 1 次 map/reduce 任务计算)。Reduce 端会缓存 a 表和 b 表的记录,然后每次取得一个 c 表的记录就计算一次 join 结果,类似的还有:

         SELECT a.val, b.val, c.val FROM a  JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)

       这里用了 2 次 map/reduce 任务。第一次缓存 a 表,用 b 表序列化;第二次缓存第一次 map/reduce 任务的结果,然后用 c 表序列化。

    3、Join 发生在 WHERE 子句之前

       如果你想限制 join 的输出,应该在 WHERE 子句中写过滤条件——或是在 join 子句中写。这里面一个容易混淆的问题是表分区的情况:

        SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)  WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

       会 join a 表到 b 表(OUTER JOIN),列出 a.val 和 b.val 的记录。WHERE 从句中可以使用其他列作为过滤条件。但是,如前所述,如果 b 表中找不到对应 a 表的记录,b 表的所有列都会列出 NULL,包括 ds 列。也就是说,join 会过滤 b 表中不能找到匹配 a 表 join key 的所有记录。这样的话,LEFT OUTER 就使得查询结果与 WHERE 子句无关了。

       解决的办法是在 OUTER JOIN 时使用以下语法:

         SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key AND   b.ds='2009-07-07' AND   a.ds='2009-07-07')

       这一查询的结果是预先在 join 阶段过滤过的,所以不会存在上述问题。这一逻辑也可以应用于 RIGHT FULL 类型的 join 中。

  14、各种排序

    order by 对所有的输入做全局排序  ,就是使用一个reducer输出结果,效率最低           全局排序

    sort by '不是全局排序, 保证每个输出有序,不保证全局有序                                     部分排序,且在进入reducer前完成排序。并不保证相同的字段会进入同一个reducer,每一个reducer的输出中,都是根据字段排序过后的,但是所有的合并起来,并不是排序的:第一个文件总有a,b,  第二个文件中也有a,b, 字段a 一定在b前头,但是文件合并后,全局无序。

    distributed by  在sort by 的基础上,先根据字段分配到同一个reducer中,然后在排序, 部分排序,相同的字段会在一起,但是并没有按照字段进行排序,例如某个reducer的输出中文件内容顺序为a, b, a, b, b,  a  ,字段本身是无序的,但是可以可定的是:字段值为a的数据肯定都在这一个文件中了。

    cluster by 这个是合并了sort by 和 distributed by 两者的排序规则:相同字段的数据都在一起,且按照这个字段值进行了排序。 

  15、索引

  16、函数:udf,udtf,udaf

    udf:user define function 用户自定义函数 表示一行数据中的一列或多列作为参数然后返回结果是一个值的函数

    udtf:user define table function 用户自定义表函数  接受0个或多个输入,然后产生多列和多行输出,例如 array函数将一组列当成一个结果输出,explode()函数以array为输入,输出多行

    udaf:user define aggregate function 用户自定义聚合函数   接受多行数据,然后返回单一值 例如,avg, sum, count等

  17、hive处理数据倾斜:见http://www.cnblogs.com/ggjucheng/archive/2013/01/03/2842860.html

posted @ 2017-09-04 17:12  IT豪哥  阅读(164)  评论(0编辑  收藏  举报