创建数据库
create database mydb;
切换数据库
use mydb;
创建数据库
create database if not exists mydb;
创建内部表表的同时加载数据
create table student_test(id INT, info struct<name:STRING, age:INT>) ROW FORMAT DELIMITED FIELDS
TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY ':';
创建外部表
create external table xxx location '/dir';
查看表信息
describe t1;
查看表的详细信息
describe extended t1;
删除数据库级联删除数据库中的表
DROP DATABASE [IF EXISTED] mydb [CASCADE];
修改列的名称、类型、位置、注释
ALTER TABLE t3 CHANGE COLUMN old_name new_name String COMMENT '...' AFTER column2;
增加列
ALTER TABLE t3 ADD COLUMNS (gender int);
从本地文件系统加载数据到表中
load data local inpath '/root/inner_table.dat' into table t1;
从hdfs加载数据到表中
load data inpath '/root/inner_table.dat' into table t1;
创建分区表
create table partition_table(rectime string,msisdn string) partitioned by(province string,city string) row format
delimited fields terminated by '\t' stored as TEXTFILE;
加载数据到分区表
load data local inpath 'files/stu' into table partition_table partition(province='beijing',city='chaoyang');
查看分区
show partitions partition_table;
删除分区
alter table partition_table drop partition (daytime='2013-02-04',city='bj')元数据,数据文件删除,但目录
daytime=2013-02-04还在
桶是更为细粒度的数据范围划分,它能使一些特定的查询效率更高,比如对于具有相同的桶划分并且join的列刚好就
是在桶里的连接查询,还有就是示例数据,对于一个庞大的数据集我们经常需要拿出来一小部分作为样例,然后在样
例上验证我们的查询,优化我们的程序。
桶表是对数据进行哈希取值,然后放到不同文件中存储。
创建表
create table bucket_table(id string) clustered by(id) sorted by (id) into 4 buckets;插入时先对id取hash值,然后对4取
模分到四个桶中
加载数据
set hive.enforce.bucketing = true;默认是false,启用桶表必须先设置该变量
insert into table bucket_table select id from stu;
insert overwrite table bucket_table select id from stu;覆盖原来数据
数据加载到桶表时,会对分桶的字段取hash值,然后与桶的数量取模。把数据放到对应的文件中。
抽样查询
select * from bucket_table tablesample(bucket 1 out of 4 on id);
tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64份,当y=32
时,抽取 (64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。x表示从哪个bucket开始抽取。
例 如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为
第3个bucket和第(3+16=)19个bucket的数据。
从文件中装载数据
hive>LOAD DATA [LOCAL] INPATH '...' [OVERWRITE] INTO TABLE t2 [PARTITION (province='beijing')];
通过查询表装载数据
hive>INSERT OVERWRITE TABLE t2 PARTITION (province='beijing') SELECT * FROM xxx WHERE xxx
一次插入多个表
hive>FROM t4
INSERT OVERWRITE TABLE t1 SELECT ...WHERE...
INSERT OVERWRITE TABLE t2 PARTITION (...) SELECT ...WHERE...
INSERT OVERWRITE TABLE t3 PARTITION (...) SELECT ...WHERE...
动态分区装载数据【动态分区列写在select子句最后】
hive>set hive.exec.dynamic.partition=true; 启用动态分区
hive>set hive.exec.dynamic.partition.mode=nostrict; 非严格模式
hive>set hive.exec.max.dynamic.partitions.pernode=1000; 最大分区数(目的是限制产生过多文件夹)
hive>INSERT OVERWRITE TABLE t3 PARTITION(province, city)
SELECT t.province, t.city FROM temp t;
如果是严格模式,必须指定一个静态分区,不能全都是动态分区
hive>INSERT OVERWRITE TABLE t3 PARTITION(province='bj', city)
SELECT t.province, t.city FROM temp t WHERE t.province='bj';
导出hive中的数据
可以使用hadoop命令进行文件复制 hdfs dfs -cp source destination
完整建表语句(注意关键字顺序)
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]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]
[SKEWED BY (col_name, col_name, ...) ON ([(col_value, col_value, ...), ...|col_value, col_value, ...])
[STORED AS DIRECTORIES] ]
[ [ROW FORMAT row_format]
[STORED AS file_format] | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] ]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement] (Note: not supported when creating external tables.)
hive处理的文件格式
TextFile: 普通文本文件,默认按该类型存储 不做压缩,磁盘开销大,数据解析开销大
SequenceFile: Hadoop API提供的一种二进制文件支持 可分割、可压缩 支持三种压缩选择:NONE, RECORD,
BLOCK。 Record压缩率低,一般建议使用BLOCK压缩
RCFile:是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个
记录需要读取多个block。其次,block中数据按列式存储,有利于数据压缩和快速的列存取。
ORC:
textfile 存储空间消耗比较大,并且压缩的text 无法分割和合并 查询的效率最低,可以直接存储,加载数据的速度最高
sequencefile 存储空间消耗最大,压缩的文件可以分割和合并 查询效率高,需要通过text文件转化来加载
rcfile 存储空间最小,查询的效率最高 ,需要通过text文件转化来加载,加载的速度最低
创建表按SequenceFile格式存储,并设置压缩形式,最后从其他表插入数据
create table test2(str STRING) STORED AS SEQUENCEFILE;
hive> set hive.exec.compress.output=true;
hive> set mapred.output.compress=true;
hive> set mapred.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;
hive> set io.seqfile.compression.type=BLOCK;
hive> set io.compression.codecs=com.hadoop.compression.lzo.LzoCodec;
hive> INSERT OVERWRITE TABLE test2 SELECT * FROM test1;
创建ORC格式存储表
hive> create table t1_orc(id int, name string) row format delimited fields terminated by '\t' stored as orc
tblproperties("orc.compress"="ZLIB");
将其他类型的表转成ORC格式表
ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT ORC
设置默认存储格式为ORC
hive> SET hive.default.fileformat=Orc;
hive> insert overwrite table t1_orc select * from t1;
What is a SerDe?
SerDe 是 "Serializer and Deserializer."的缩写
Hive 使用 SerDe和FileFormat进行行内容的读写.
HDFS文件 --> InputFileFormat --> <key, value> --> Deserializer --> 行对象
行对象 --> Serializer --> <key, value> --> OutputFileFormat --> HDFS文件
Hive 使用如下FileFormat 类读写 HDFS files:
TextInputFormat/HiveIgnoreKeyTextOutputFormat: 读写普通HDFS文本文件.
SequenceFileInputFormat/SequenceFileOutputFormat: 读写SequenceFile格式的HDFS文件.
例:
CSV格式的文件也称为逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可
以不是逗号。在本文中的CSV格式的数据就不是简单的逗号分割的),其文件以纯文本形式存储表格数据(数字和文
本)。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字
符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。
默认的分隔符是
DEFAULT_ESCAPE_CHARACTER \
DEFAULT_QUOTE_CHARACTER " ---如果没有,则不需要指定
DEFAULT_SEPARATOR ,
CREATE TABLE csv_table(a string, b string) ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES ( "separatorChar" = "\t",
"quoteChar" = "'", "escapeChar" = "\\") STORED AS TEXTFILE;
红色部分为默认,也可以不写。
该类org.apache.hadoop.hive.serde2.OpenCSVSerde即包含了InputFormat和OutputFormat来处理csv文件。
什么时候可以避免执行MapReduce?
select * where语句中只有分区字段
set hive.exec.mode.local.auto=true;
group by语句
having语句
order by、sort by、distribute by、cluster by语句
order by是全局排序、sort by是单reduce排序、distribute by是分区字段;
cluster by是distribute by和sort by的简写
性能调优
set hive.map.aggr=true;
这个设置可以将顶层的聚合操作放在Map阶段执行,从而减轻清洗阶段数据传输和Reduce阶段的执行时间,提升总
体性能。
缺点:该设置会消耗更多的内存。
表连接:
INNER JOIN
表中都有,且两表符合连接条件
LEFT OUTER JOIN
左表中符合where条件出现,右表可以为空
RIGHT OUTER JOIN
右表中符合where条件出现,左表可以为空
FULL OUTER JOIN
LEFT SEMI-JOIN (左半连接)
左表中符合on条件出现,右表不出现
笛卡尔积
是m x n的结果
map-side JOIN
视图的创建
CREATE VIEW v1 AS select * from t1;
lateral view用于和split, explode等UDTF一起使用,它能够将一行数据拆成多行数据,在此基础上可以对拆分后的数
据进行聚合。lateral view首先为原始表的每行调用UDTF,UTDF会把一行拆分成一或者多行,lateral view再把结果组
合,产生一个支持别名表的虚拟表。
SELECT pageid, adid FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;
自定义函数:
1、UDF函数可以直接应用于select语句,对查询结构做格式化处理后,再输出内容。
2、编写UDF函数的时候需要注意一下几点:
a)自定义UDF需要继承org.apache.hadoop.hive.ql.UDF。
b)需要实现evaluate函数,evaluate函数支持重载。
4、步骤
a)把程序打包放到目标机器上去;
b)进入hive客户端,添加jar包:hive>add jar /run/jar/udf_test.jar;
c)创建临时函数:hive>CREATE TEMPORARY FUNCTION add_example AS 'hive.udf.Add';
d)查询HQL语句:
SELECT add_example(8, 9) FROM scores;
SELECT add_example(scores.math, scores.art) FROM scores;
SELECT add_example(6, 7, 8, 6.8) FROM scores;
e)销毁临时函数:hive> DROP TEMPORARY FUNCTION add_example;
注:UDF只能实现一进一出的操作,如果需要实现多进一出,则需要实现UDAF
使用jdbc访问hive
首先开启hive远程端口
Hive远程服务启动#hive --service hiveserver -p 10002 >/dev/null 2>/dev/null &
JAVA客户端相关代码
Class.forName("org.apache.hadoop.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection("jdbc:hive://192.168.1.102:10000/wlan_dw", "", "");
Statement stmt = con.createStatement();
String querySQL="SELECT * FROM wlan_dw.dim_m order by flux desc limit 10";
ResultSet res = stmt.executeQuery(querySQL);
while (res.next()) {
System.out.println(res.getString(1) +"\t" +res.getLong(2)+"\t" +res.getLong(3)+"\t" +res.getLong(4)+"\t"
+res.getLong(5));
}
JOIN 优化
1.hive对3个或3个以上的表进行join操作时,如果每个on字句都使用相同的连接键的话,只会产生一个MapReduce
job。
2.hive会假定查询中最后一个表示最大的那个表。在对每行记录进行连接操作时,会将其他表缓存起来,然后扫描最
后那个表进行计算。所以要保证从左到右表的大小是依次增加的。也可以在查询语句中加入 /*+STREAMTABLE(表名
或别名)*/,指定哪张是最大的表。
3.避免笛卡尔积,select * from a join b where ....。在执行where过滤前首先会对a表和b表进行笛卡尔积,导致过程非
常缓慢,在hive中设置hive.mapred.mode=strict可以阻止笛卡尔积。
4.map-side join 如果连接查询中只有一张表是小表,可以将小表中的数据放到内存中,在map端就可以进行连接操作
省略了reduce端的过程。需要设置 hive.auto.convert.join=true 并设置小表的大小hive.mapjoin.smalltable.filesize单位
是字节。或在查询中加入 /*+ MAPJOIN(表名或别名)*/