Hive学习之常见问题

HiveSQL 的原理:我们都知道 HiveSQL 会被翻译成 MapReduce 任务执行,那么一条 SQL 是如何翻译成MapReduce 的?

详细! 需要多看几遍才能看懂
https://www.aboutyun.com/thread-20461-1-1.html

Hive 和普通关系型数据库有什么区别?
1.查询语言不同:hive是hql语言,mysql是sql语句;

2.数据存储位置不同:hive是把数据存储在hdfs上,而mysql数据是存储在自己的系统中;

3.数据格式:hive数据格式可以用户自定义,mysql有自己的系统定义格式;

4.数据更新:hive不支持数据更新,只可以读,不可以写,而sql支持数据更新;

5.索引:hive没有索引,因此查询数据的时候是通过mapreduce很暴力的把数据都查询一遍,也造成了hive查询数据速度很慢的原因,而mysql有索引;

6.延迟性:hive延迟性高,原因就是上边一点所说的,而mysql延迟性低;

7.数据规模:hive存储的数据量超级大,而mysql只是存储一些少量的业务数据;

8.底层执行原理:hive底层是用的mapreduce,而mysql是excutor执行器;
————————————————
版权声明:本文为CSDN博主「老子天下最美」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Sunshine_2211468152/article/details/83031356

HQL 和 SQL 有哪些常见的区别

在这里插入图片描述

Hive 支持哪些数据格式

Hive支持原始数据类型和复杂类型,原始类型包括数值型,Boolean,字符串,时间戳。复杂类型包括array,map,struct,union。

原始数据类型:

类型名称 大小 备注
TINYINT 1字节整数 45Y
SMALLINT 2字节整数 12S
INT 4字节整数 10
BIGINT 8字节整数 244L
FLOAT 4字节单精度浮点数 1.0
DOUBLE 8字节双精度浮点数 1.0
DECIMAL 任意精度带符号小数 DECIMAL(4, 2)范围:-99.99到99.99
BOOLEAN true/false TRUE
STRING 字符串,长度不定 “a”, ‘b’
VARCHAR 字符串,长度不定,有上限 0.12.0版本引入
CHAR 字符串,固定长度 “a”, ‘b’
BINARY 存储变长的二进制数据
TIMESTAMP 时间戳,纳秒精度 122327493795
DATE 日期 ‘2016-07-03’

复杂类型:

类型名称 大小 示例
ARRAY 存储同类型数据 ARRAY< data_type>
MAP key-value,key必须为原始类型,value可以是任意类型 MAP< primitive_type, data_type>
STRUCT 类型可以不同 STRUCT< col_name : data_type [COMMENT col_comment], …>
UNION 在有限取值范围内的一个值 UNIONTYPE< data_type, data_type, …>

Hive 在底层是如何存储 NULL 的

HIVE表中默认将NULL存为\N,可查看表的源文件(hadoop fs -cat或者hadoop fs -text),文件中存储大量\N, 这样造成浪费大量空间。而且用java、python直接进入路径操作源数据时,解析也要注意。另外,hive表的源文件中,默认列分隔符为\001(SOH),行分隔符为\n(目前只支持\n,别的不能用,所以定义时不需要显示声明)。元素间分隔符\002,map中key和value的分隔符为\003。

举例,如源文件中一条记录为:

10000042SOH77SOH435SOH16SOH22SOH1156120000SOH\NSOH\NSOH\NSOH\NSOH\NSOH\NSOH\NSOHyoukuSOH85133.0SOH111

可以看出存储NULL的\N 浪费了大量空间。**但hive的NULL有时候是必须的:1)hive中insert语句必须列数匹配,不支持不写入,没有值的列必须使用null占位。2)hive表的数据文件中按分隔符区分各个列。**空列会保存NULL(\n)来保留列位置。但外部表加载某些数据时如果列不够,
如表13列,文件数据只有2列,则在表查询时表中的末尾剩余列无数据对应,自动显示为NULL。所以,NULL转化为空字符串,可以节省磁盘空间,实现方法有几种
1)建表时直接指定(两种方式)
a、用语句ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe’
with serdeproperties(‘serialization.null.format’ = ‘’)
实现,注意两者必须一起使用,如
CREATETABLE hive_tb (idint,name STRING)
PARTITIONED BY (day string,type tinyint COMMENT’0 as bid, 1 as win, 2 as ck’,hour tinyint)
ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe’
WITH SERDEPROPERTIES (‘field.delim’=’/t’,‘escape.delim’=’//’,serialization.null.format’=’’ )
STORED AS TEXTFILE;
b、或者通过ROW FORMAT DELIMITED NULL DEFINED AS ‘‘如
CREATETABLE hive_tb (idint,name STRING)
PARTITIONED BY (day string,type tinyint COMMENT’0 as bid, 1 as win, 2 as ck’,hour tinyint)
ROW FORMAT DELIMITED
NULL DEFINEDAS’’
STORED AS TEXTFILE;
2)修改已存在的表
alter table hive_tb set serdeproperties(‘serialization.null.format’ = ‘’);

HiveSQL 支持的几种排序各代表什么意思(Sort By/Order By/Cluster By/Distrbute By)
这个写的差不多了
https://blog.csdn.net/lzm1340458776/article/details/43306115?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1

原博主应该是加了℃ 所以排序有点问题
去掉就正常了
在这里插入图片描述

cluster by =
cluster by的功能就是distribute by和sort by相结合

Hive 的动态分区
往hive分区表中插入数据时,如果需要创建的分区很多,比如以表中某个字段进行分区存储,则需要复制粘贴修改很多sql去执行,效率低。因为hive是批处理系统,所以hive提供了一个动态分区功能,其可以基于查询参数的位置去推断分区的名称,从而建立分区。

1.创建一个单一字段分区表

1 hive>
2    create table dpartition(id int ,name string )
3    partitioned by(ct string  );

2.往表里装载数据,并且动态建立分区,以city建立动态分区

hive>
 hive.exec.dynamici.partition=true;  #开启动态分区,默认是false
 set hive.exec.dynamic.partition.mode=nonstrict; #开启允许所有分区都是动态的,否则必须要有静态分区才能使用。
 insert overwrite table dpartition
 partition(ct)
 select id ,name,city from  mytest_tmp2_p; 
 
要点:因为dpartition表中只有两个字段,所以当我们查询了三个字段时(多了city字段),所以系统默认以最后一个字段city为分区名,因为分区表的
分区字段默认也是该表中的字段,且依次排在表中字段的最后面。所以分区需要分区的字段只能放在后面,不能把顺序弄错。如果我们查询了四个字段的话,则会报
错,因为该表加上分区字段也才三个。要注意系统是根据查询字段的位置推断分区名的,而不是字段名称。
hive>--查看可知,hive已经完成了以city字段为分区字段,实现了动态分区。
hive (fdm_sor)> show partitions dpartition;
partition
ct=beijing
ct=beijing1

注意:使用,insert…select 往表中导入数据时,查询的字段个数必须和目标的字段个数相同,不能多,也不能少,否则会报错。但是如果字段的类型不一致的话,则会使用null值填充,不会报错。而使用load data形式往hive表中装载数据时,则不会检查。如果字段多了则会丢弃,少了则会null值填充。同样如果字段类型不一致,也是使用null值填充。

3.多个分区字段时,实现半自动分区(部分字段静态分区,注意静态分区字段要在动态前面)

 1 1.创建一个只有一个字段,两个分区字段的分区表
 2 hive (fdm_sor)> create table ds_parttion(id int ) 
 3               > partitioned by (state string ,ct string );
 4 2.往该分区表半动态分区插入数据 
 5 hive>
 6  set hive.exec.dynamici.partition=true;
 7  set hive.exec.dynamic.partition.mode=nonstrict;
 8  insert overwrite table ds_parttion
 9  partition(state='china',ct)  #state分区为静态,ct为动态分区,以查询的city字段为分区名
10  select id ,city from  mytest_tmp2_p; 
11  
12 3.查询结果显示:
13 hive (fdm_sor)> select *  from ds_parttion where state='china'
14               > ;
15 ds_parttion.id  ds_parttion.state       ds_parttion.ct
16 4       china   beijing
17 3       china   beijing
18 2       china   beijing
19 1       china   beijing
20 4       china   beijing1
21 3       china   beijing1
22 2       china   beijing1
23 1       china   beijing1
24  
25 hive (fdm_sor)> select *  from ds_parttion where state='china' and ct='beijing';
26 ds_parttion.id  ds_parttion.state       ds_parttion.ct
27 4       china   beijing
28 3       china   beijing
29 2       china   beijing
30 1       china   beijing
31  
32 hive (fdm_sor)> select *  from ds_parttion where state='china' and ct='beijing1';
33 ds_parttion.id  ds_parttion.state       ds_parttion.ct
34 4       china   beijing1
35 3       china   beijing1
36 2       china   beijing1
37 1       china   beijing1
38 Time taken: 0.072 seconds, Fetched: 4 row(s)

4.多个分区字段时,全部实现动态分区插入数据

1  set hive.exec.dynamici.partition=true;
2  set hive.exec.dynamic.partition.mode=nonstrict;
3  insert overwrite table ds_parttion
4  partition(state,ct)
5  select id ,country,city from  mytest_tmp2_p; 
6 注意:字段的个数和顺序不能弄错。

5.动态分区表的属性
使用动态分区表必须配置的参数 :

  set hive.exec.dynamic.partition =true(默认false,表示开启动态分区功能
    set hive.exec.dynamic.partition.mode = nonstrict(默认strict),表示允许所有分区都是动态的,否则必须有静态分区字段

动态分区相关的调优参数:

set  hive.exec.max.dynamic.partitions.pernode=100 (默认100,一般可以设置大一点,比如1000

表示每个maper或reducer可以允许创建的最大动态分区个数,默认是100,超出则会报错。

   set hive.exec.max.dynamic.partitions =1000(默认值) 

表示一个动态分区语句可以创建的最大动态分区个数,超出报错

   set hive.exec.max.created.files =10000(默认) 全局可以创建的最大文件个数,超出报错。

Hive 中的内部表和外部表的区别

内部表和外部表在创建的时候稍微有一点区别:

1.默认情况下是内部表(managed table)

2.外部表(external table)创建的时候需要加上external关键字,并且需要指定位置

3.删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;

4.内部表数据由Hive自身管理,外部表数据由HDFS管理

5.内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己指定;

6.对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name;)

没明白“desc formated t1 ”是什么意思啊?查看该表当前的格式和详细信息

“desc t1”又是什么意思啊?查看该表的字段情况
————————————————
版权声明:本文为CSDN博主「道法—自然」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wyqwilliam/article/details/81061038

Hive 表进行关联查询如何解决长尾和数据倾斜问题
HiveSQL 的优化(系统参数调整、SQL 语句优化)
明日解决

发布了6 篇原创文章 · 获赞 6 · 访问量 502

猜你喜欢

转载自blog.csdn.net/qq_41130274/article/details/105422536