以下是本篇文章正文内容,如有错误麻烦请指出。 谢谢 !!!
Hive的parquet表支持的数据类型:
INT,TINYINT,SMALLINT,BIGINT,FLOAT,STRING, BOOLEAN,
CHAR,VARCHAR,DECIMAL,DOUBLE,BINARY,TIMESTAMP
Impala的parquet表支持的数据类型:
TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,DECIMAL,STRING,CHAR,VARCHAR,TIMESTAMP
Hive的文件存储格式包括:textfile, sequencefile, rcfile, orc, parquet
1)TextFile
每一行都是一条记录,每行都以换行符(\ n)结尾。数据不做压缩,磁盘开销大,数据解析开销大。可结合
Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而
无法对数据进行并行操作。
2)SequenceFile
是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点。
支持三种压缩选择:NONE, RECORD, BLOCK。 Record压缩率低,一般建议使用BLOCK压缩。
3)RCFile
是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记
录需要读取多个block。其次,块数据列式存储,有利于数据压缩和快速的列存取。
4)AVRO
是开源项目,为Hadoop提供数据序列化和数据交换服务。您可以在Hadoop生态系统和以任何编程语言编写的
程序之间交换数据。Avro是基于大数据Hadoop的应用程序中流行的文件格式之一。
5)ORC文件代表了优化排柱状的文件格式。
ORC文件格式提供了一种将数据存储在Hive表中的高效方法。这个文件系统实际上是为了克服其他Hive文件
格式的限制而设计的。Hive从大型表读取,写入和处理数据时,使用ORC文件可以提高性能。
6)Parquet
是一个面向列的二进制文件格式。Parquet对于大型查询的类型是高效的。对于扫描特定表格中的特定列的
查询,Parquet特别有用。Parquet格式使用压缩Snappy,gzip;目前Snappy默认。
1)TextFile默认的文件格式,行存储。建表时不指定存储格式即为textfile,导入数据时把数据文件拷贝至hdfs不进行处理。
a.优点:最简单的数据格式,便于和其他工具(Pig, grep, sed, awk)共享数据,便于查看和编辑;加载较快。
b.缺点:耗费存储空间,I/O性能较低;Hive不进行数据切分合并,不能进行并行操作,查询效率低。
c.适用于小型查询,查看具体数据内容的测试操作。
2)SequenceFile含有键值对的二进制文件,行存储。
a.优点:可压缩、可分割,优化磁盘利用率和I/O;可并行操作数据,查询效率高;
b.缺点:存储空间消耗最大;对于Hadoop生态系统之外的工具不适用,需要通过text文件转化加载。
c.适用于数据量较小、大部分列的查询。
3)RcFile行列式存储。先将数据按行分块,同一个record在一个块上,避免读一条记录需要读多个block;然后块数据列式存储。
a.优点:可压缩,高效的列存取;查询效率较高;存储空间最小;查询的效率最高。
b.缺点:加载时性能消耗较大,需要通过text文件转化加载;读取全量数据性能低;加载的速度最低。
4)ORC
a.优化后的rcfile,行列式存储。
b.优缺点与rcfile类似,查询效率最高。
c.适用于Hive中大型的存储、查询。
5)Parquet列存储
a.优点:更高效的压缩和编码;不与任何数据处理技术绑定,可用于多种数据处理框架(Hive, Impala, Presto查询
引擎;MapReduce, Spark计算框架;Avro, Thrift, PB数据模型 )。
b.缺点:不支持update, insert, delete, ACID
c.适用于字段数非常多,无更新,只取部分列的查询。
第一种连接方式
1、启动 hiveserver2
2、beeline -u jdbc:hive2://IP:10000 -n hive
第二种连接方式
1、执行 beeline 命令
2、接着执行 !connect jdbc:hive2://IP:10000
3、根据2的提示输入用户 hive 密码 ppwd1234
内容:
DROP TABLE DEFAULT.USER_INFO_TEST;
CREATE TABLE DEFAULT.USER_INFO_TEST (name VARCHAR(40),
age INT,
gender VARCHAR(10) )
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
外部表删除表不删除数据文件,而内部表会同数据一起删除。
注:内部表与外部表有个关键字 ”EXTERNAL“ 标识,外部表可以通过关键字 ”LOCATION“ 指定数据文件在hdfs
上的目录
内部表:
CREATE TABLE DEFAULT.USER_INFO_TEST (name VARCHAR(40),
age INT,
gender VARCHAR(10)
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '#' LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
外部表:
CREATE EXTERNAL TABLE DEFAULT.USER_INFO_TEST2 (name VARCHAR(40),
age INT,
gender VARCHAR(10)
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '#' LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
外部表指定文件存放目录
CREATE EXTERNAL TABLE DEFAULT.USER_INFO_TEST3 (name VARCHAR(40),
age INT,
gender VARCHAR(10)
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '#' LINES TERMINATED BY '\n'
LOCATION "/tmp/USER_INFO_TEST3";
分区表:
CREATE TABLE IF NOT EXISTS TDSHDATA.T03_AGREEMENT (`AGMT_NUM` CHAR(40) COMMENT '协议号'
,`AGMT_MODIFIER_NUM` CHAR(8) COMMENT '协议修饰符'
,`AGMT_CATEG_CD` CHAR(2) COMMENT '协议类别代码'
,`ETL_PROC_DT` TIMESTAMP COMMENT 'ETL首次插入日期')
COMMENT '协议表'
PARTITIONED BY(`AGMT_SRC_SYS_ID` CHAR(4) COMMENT '协议来源系统编号')
STORED AS parquet;
CREATE TABLE TABLENAME LIKE TBNAME2;
注:通过LOAD加载数据,分为本地加载和HDFS加载,通过关键字”LOCAL“标识
LOAD DATA LOCAL INPATH '/home/data/xxx.txt' OVERWRITE INTO TABLE TABLENAME;
LOAD DATA INPATH '/home/data/xxx.txt' OVERWRITE INTO TABLE TABLENAME;
LOAD DATA INPATH '/home/data/xxx.txt' OVERWRITE INTO TABLE TABLENAME PARTITION (PART1 = 'DATE');
注:此方法会存入数据。但是这个不能用于创建外部表。
CREATE TABLE TBNAME AS SELECT * FROM TBNAME2;
,删除表,删除数据库,删除分区,添加分区,模糊查询表,修改表名,添加字段,修改字段
清空表数据:TRUNCATE TABLE TABLENAME;
删除表:DROP TABLE IF EXISTS TABLENAME;
删除数据库:DROP DATABASE IF EXISTS DATABASENAME; 注:数据库要为空
删除数据库:DROP DATABASE IF EXISTS TDSHDATA_BAK CASCADE; 注:强制删除库
删除分区:ALTER TABLE TABLENAME DROP IF EXISTS PARTITION(P_COLUMNS = 'VALUES');
注:表要存在分区字段
添加分区:ALTER TABLE TABLENAME ADD IF NOT EXISTS ADD PARTITION(P_COLUMNS = 'VALUES'); 注:表要存在分区字段
模糊查询表:SHOW TABLES LIKE '*NAME*';
修改表名:ALTER TABLE TABLENAME1 RENAME TO TABLENAME2;
添加字段:ALTER TABLE TABLENAME ADD COLUMNS(COLUMNS_NAME COLUMNS_TYPE COMMENT '中文名');
添加字段:ALTER TABLE TABLENAME CHANGE COLUMN OLDER_COLUMN_NAME NEW_COLUMN_NAME
NEW_TYPE COMMENT '新的中文名' [FIRST|AFTER COLUMNS_NAME];
注: [FIRST|AFTER COLUMNS_NAME] 表示修改的字段放置的位置,
FIRST表示放置第一位,
AFTER COLUMNS_NAME表示放在该字段的后一位。
ALTER TABLE TABLENAME SET FILEFORMAT FILE_FORMAT_NAME;
注:这只是改变了表的文件格式,实际的数据文件格式没有改变。
ALTER TABLE TABLENAME CLUSTERED BY (COLUMN1, COLUMN2, COLUMN3, ...)
[SORTED BY(COLUMN1, COLUMN2, ...)] INTO NUM_BUCKETS BUCKETS;
视图表创建:
CREATE VIEW IF NOT EXISTS DATABASE_VIEW.VIEW_TABLE_NAME
AS SELECT * FROM DATABASE.TABLE_NAME;
应用视图表的原因:
主要还是因为对表管理的安全考虑,视图表实际不存放数据,使用的数据还是源表中的数据,只能对视图表查
询操作,其他操作对视图表无效!
如果编码为UTF-8,需要通过执行sql:alter database hive default character set latin1;
修改为hive的默认编码:latin1。(Latin1)
cd /data/mysql/data/mysql-5.7.20/bin
./mysql -u root -p'mysqlroot' --socket=/data/mysqldata/3306/mysql.sock
2.1:use hive;
2.2:alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8;
2.3:alter table TABLE_PARAMS modify param_value varchar(4000) character set utf8;
2.4:alter table PARTITION_PARAMS modify param_value varchar(4000) character set utf8;
2.5:alter table PARTITION_KEYS modify pkey_comment varchar(4000) character set utf8;
2.6:alter table INDEX_PARAMS modify param_value varchar(4000) character set utf8;
刷新:flush privileges;
INSERT INTO TABLE A PARTITION(A.COLUMNS) SELECT COLUMNS1, COLUMNS2 FROM B;导入动态分区
例如:
CREATE TABLE B (S VARCHAR(20),
D VARCHAR(20),
F VARCHAR(20),
G VARCHAR(20)
) STORED AS TEXTFILE;
CREATE TABLE A (S VARCHAR(20),
D VARCHAR(20),
F VARCHAR(20)
) PARTITIONED BY (G VARCHAR(20))
STORED AS PARQUET;
set hive.exec.dynamic.partition=true; -- 开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict; -- 设置Hive允许创建动态分区
set hive.exec.max.dynamic.partitions.pernode=1000; -- 表示每个Map或Reducer可以允许创建的最大动
态分区个数,默认100,超出会报错
set hive.exec.max.dynamic.partitions=3000; --设置Hive允许一个动态分区语句允许创建最大动态分区的
个数,超出会报错!
set hive.exec.max.created.files=10000(默认) -- 全局可以创建的最大文件个数,超出报错;
插入语句:INSERT INTO TABLE A PARTITION(G) SELECT S, D, F, G FROM B;
1.1、桶表是对某一列数据进行哈希取值以将数据打散,然后放到不同的文件中存储;
1.2、在Hive分区中,分区的数据量过于庞大时,建议使用桶;
1.3、在分桶时,对指定字段的值进行hash运算得到hash值,并使用hash值除以桶的个数做取余运算得到的值
进行分桶,保证每个桶中有数据但每个桶中数据不一定相等;做hash运算时,hash函数的选择取决于分桶字
段的数据类型;
1.4、分桶后的查询效率比分区后的查询效率更高。
注:如果没有加入 SORTED BY(字段) 会导致数据可能不会分桶。
CREATE TABLE TABLENAME(ID INT,
AGE INT,
NAME VARCHAR(30))
CLUSTERED BY(ID) SORTED BY(ID) INTO 4 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY '#' LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
桶表不能通过Load的方式加载数据,只能从另一张表中插入数据
例如:INSERT INTO TABLE TEST02 SELECT * FROM TEST01;
4.1、环境配置,使Hive能够识别通
设置如下配置:vim ~/.hiverc
添加:set hive.enforce.bucketing=true
注:~/.hiverc 原有内容如下:
set hive.cli.print.current.db=true
set hive.cli.print.header=true
4.2、修改桶表中bucket数量
ALTER TABLE TABLENAME CLUSTERED BY(ID) SORTED BY(AGE) INTO 10 BUCKETS;
4.3、Hive中的抽样查询
SELECT * FROM TABLENAME TABLESAMPLE(BUCKET X OUT OF Y ON FIELD_NAME);
注:X表示从那个桶开始抽取,Y表示相隔多少桶再次抽取。
Y必须为分桶数量的倍数或者因子,比如分桶数为6,Y为6,则表示只从桶中抽取1个bucket的数据;若Y为3,
则表示从从中抽取6/3=2个bucket的数据。
4.4、Hive视图 (按需查询,提高查询效率)
例如:CREATE VIEW BKTVIEW AS SELECT ID, NAME, AGE FROM TABLENAME;
注:创建视图只是创建一个与源表的映射,视图中的字段由用户按需决定。
1.1、将大表放后头
Hive假定查询中最后一张表是大表,它会将其它表缓存起来,然后扫描最后那个表。因此通常需要将小表
放前面,或者标记那张表是大表:/*streamtable(TABLENAME)*/。
1.2、使用相同的连接键
当对3个或者更多个表进行join连接时,如果每个on子句都使用相同的连接键的话,那么只会产生一个MR Job。
1.3、尽量早地过滤数据
减少每个阶段的数据量,对于分区表加分区,同时只选择需要使用到的字段。
1.4、尽量原子化操作
尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑。
2.1、如果 UNION ALL 的部分个数大于2,或者每个 UNION ALL 部分的数据量很大,应该拆成多个 INSERT INTO
语句,实际测试过程中,执行的时间能提升50%。
3.1、ORDER BY:对查询结果进行全局排序,消耗时间长。需要设置:set hive.mapred.mode=nostrict。
3.2、SORT BY:局部排序,并非全局排序,提高效率。
4.1、一种嵌入在Hive取数流程中的自定义函数,通过TRANSFORM语句可以把在Hive中不方便实现的功能在
Python中实现,然后写入Hive中。
注:语法:SELECT TRANSFORM(FIELD_NAME) using '**.py' AS FIELD_NAME FROM {TABLENAME};
如果Python脚本外还有其他依赖资源,可以使用ADD ARVHIVE。
5.1、一般情况下,LIMIT语句还是需要执行整个查询语句,然后再返回部分结果。
注:解决办法
有一个配置属性可以开启,避免这种情况---对数据源进行抽样
5.1.1、hive.limit.optimize.enable=true --- 开启对数据源进行采样的功能;
5.1.2、hive.limit.row.max.szie --- 设置最小的采样容量;
5.1.3、hive.limit.optimize.limit.file --- 设置最大的采样样本数。
缺点:有可能部分数据永远处理不到。
6.1、对于小数据集,为查询触发执行任务消耗的时间 > 实际执行Job的时间,因此可以通过本地模式,
在单台机器上(或某些时候在单个进程上)处理所有的任务。
set oldjobtracker=${hiveconf:mapred.job.tracker};
set mapred.job.tracker=local;
set mapred.tmp.dir=/home/edward/tmp;
SQL语句:set mapred.job.tracker=${oldjobtracker};
6.2、可以通过设置属性
hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化,也可以将配置写在
$HOME/.hiverc文件中。
6.3、当一个Job满足如下条件才能真正使用本地模式
6.3.1、Job的输入数据大小小于参数:
hive.exec.mode.local.auto.inputbytes.max(默认是128MB)
6.3.2、Job的Map数必须小于参数
Hive.exec.mode.local.auto.tasks.max(默认4)
6.3.3、Job的Reduce数必须为0或1
可用参数:hive.mapred.local.mem(默认0),控制child jvm 使用的最大内存数。
7.1、Hive会将一个查询转化为一个或者多个阶段,包括:MapReduce阶段、抽样阶段、合并阶段、LIMIT阶段等。
默认情况下,一次只执行一个阶段,不过如果某些阶段不是相互依赖,是可以并行执行的。
set hive.exec.parallel=true --- 可以开启并发执行;
set hive.exec.parallel.thread.number=16 --- 同一个SQL允许最大的并行度,默认为8,会比较耗系统资源。
8.1.1、Map个数主要的决定因素有:(Map执行时间:Map任务启动和初始化的时间+逻辑处理的时间)
Input的文件总个数;
Input的文件大小;
集群设置的文件块大小。
8.1.2、减少MaP数
若有大量小文件(小于128M),会产生多个Map,处理方法:(单位字节)
set mapred.max.split.size=100000000 -- 一个Split最大大小
set mapred.min.split.size.per.node=100000000; --- 一个节点上Split的至少大小
set mapred.min.split.size.per.rack=100000000; --- 一个交换机下Split至少大小
set hive.input.format=org.apache.hadoop.hive.ql.CombineHiveInputFormat
注:以上三个参数确定合并文件块的大小,大于文件块大小128M的,按照128M来分割;
若小于128M大于100M的,按照100M来分割,把那些小于100M的(包括小文件和分割大文件剩下的)进
行合并。
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
注:执行前进行小文件合并。
重建目标表将物理分区切分成多份,如下:
Create table new_table_name as select * from table_name distribute by rand(10);
8.1.3、增加Map数。
当Input的文件都很大,任何逻辑复杂,Map执行非常慢的时候,可以考虑增加Map数来使得每个Map处理的数
据量减少,从而执行任务的执行效率。
set mapred.reduce.tasks=20;
调整方式:
第一种:参数设置
set hive.exec.reducers.bytes.per.reducer=1G;
set hive.exec.reducers.max=999;
第二种:调整参数
set mapred.reduce.tasks=10;
一般根据输入文件的总大小,用它的estimation函数来自动计算Reduce的个数:
Reduce个数=InputFileSize / bytes.per.reducer
如果Hive的输入文件是大量的小文件,而每个文件启动一个Map的话是对Yarn资源的浪费,同样Hive输出的文件
也远远小于HDFS的块大小,对数据后续的处理是不利的,即需要做如下处理优化:
8.3.1、合并输入小文件
参数 参数解释 值
mapred.max.split.size 每个Map最大输入文件大小 256M
mapred.min.split.size.per.node 一个节点上split的文件至少大小 100M
mapred.min.split.size.per.rack 一个交换机下Split的文件至少大小 100M
hive.input.format 执行Map前进行小文件合并 org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
8.3.2、合并输出小文件
参数 参数解释 值
hive.merge.mapfiles -- 在Map-only的任务结束时合并小文件 True
hive.merge.mapredfiles -- 在Map-Reduce的任务结束时合并小文件 True
hive.merge.size.per.task -- 合并文件的大小 256M
hive.merge.smallfiles.avgsize -- 当输出文件的平均大小小于该值时启动一个独立的Map-Reduce任务进行
文件Merge 16M
--- 防止用户执行一些意想不到的不好的影响查询;
--- 分区表,必须选定分区范围;
--- 对于使用ORDER BY的查询,要求必须使用LIMIT语句,因为ORDER BY为了执行牌勋过程会将所有的结果数据分发到同一个Reducer中进行处理;
--- 限制笛卡尔积查询:两张表JOIN时,必须要有ON条件。
表现:任务长时间维持在99%(或100%),查看任务监控页面,发现只有少量(一个或几个)Reduce子任务没有
未完成。以为其处理的数据量和其他的Reduce差异过大。单一Reduce的记录数与平均记录数差异过大,通常可
能达到3倍甚至更多,最长时长远大于平均时长。
原因: KEY分布不均,数据本事的特性,建表是考虑不周,某些SQL语句本身就有数据倾斜
Join:其中一个表较小,但是KEY集中,分发到某一个或者几个Reduce上的数据远高于平均值;
Join:大表与大表,但是分桶的判断字段0值或者空值过多,这些空值都有一个Reduce处理,非常慢;
Group By: Group By维度过小,某值得数量过多,处理某值的Reduce非常耗时;
Count、Distinct:某特殊值过多,处理此特殊值Reduce耗时。
参数调节:hive.map.aggr=true
数据属于CSV格式,所以这里使用默认的org.apache.hadoop.hive.serde2.OpenCSVSerde类进行处理。
建表语句:
CREATE EXTERNAL TABLE CSVTABLE(
COL1 STRING,
COL2 STRING,
COL3 STRING
) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES("separatorChar" = ",",
"quoteChar" = "\"",
"escapeChar" = "\\"
) STORED AS TEXTFILE
LOCATION '/TEM/HIVE/';
建表语句:
CREATE EXTERNAL TABLE MAPTABLE(COL1 STRING,
COL2 STRING,
COL3 MAP
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY '|'
MAP KEYS TERMINATED BY ":"
STORED AS TEXTFILE
LOCATION '/TEM/HIVE/';
注:Map类型里定义了Key和Value的数据类型,
Map类型中定义的字段与示例数据中 “name:fayson|sex:男|age:18”,该数据以k-v方式存储。
Collection items terminated by "|", 表示Map中的每个k-v直接以“|”分割,
MAP KEYS TERMINATED BY ":",表示k-v之间数据以“:”分割。
查询数据的SQL使用:
select COL1, COL2, COL3['name'], COL3['age'], COL3['sex'] from MAPTABLE;
建表语句:
CREATE EXTERNAL TABLE STRUCTTABLE(COL1 STRING,
COL2 STRING,
COL3 STRUCT
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY ':'
STORED AS TEXTFILE
LOCATION '/TEM/HIVE/';
查看hive支持的压缩格式:set io.compression.codecs;
2.1、创建Parquet表:
create table mytable(a int,b int)
stored as parquet
tblproperties(‘parquet.compression’=’snappy’);
注:如果原先创建的表没有指定压缩,后续可以通过修改表属性添加表的压缩:
Alter table mytable set tblproperties(‘parquet.compression’=’snappy’)
或者在写入的时候执行:set parquet.compressio’=snappy;
注:不过只能影响后续入库的数据,原来的数据是不会压缩的,采用压缩之后大概可以降低1/3的存储大小!
Hive表数据删除之后,数据临时存放目录:/user/登录的用户/.Trash/(hdfs路径)
注:需要定期删除,否则时间长了会占用大量的hdfs空间!!!
好记性不如笔记来的实在!!!