基础知识
hive需要存储模式信息和其他元数据,默认使用关系型数据库Derby SQL。它提供有限的单进程的存储服务,例如用户不可以执行两个并发的Hive CLI实例。因此对于集群和多用户并发的场景来说,需要使用MySQL或者类似的关系型数据库,只要该数据库可以使用JDBC连接即可。
conf目录下存放了Hive的配置文件,包括元数据存储方式,各种各样的优化和安全控制等等。
如何与Hive交互
有三种方式可以访问Hive:
1,交互式的命令行界面
2,使用JDBC,ODBC(由thrift实现)。即编写Java程序,调用Hive的API来执行HQL,与在Java程序中调用关系型数据库API来操作关系型数据库是一样的。
3,Hive还提供一个简单的网页界面,提供远程访问hive的服务
下面就如何使用命令行做简单的介绍:
在操作系统命令行中执行HQL
下面的例子在操作系统命令行中执行HQL,且将结果输出到某目录:
/>hive -e “select * from mutable limit 3” > /tmp/myquery
也可以用下面的命令执行文件中的HQL
/>hive -f /path/to/file/queries.hql
在hive shell中则直接运行HQL:
hive>SELECT * from tableA;
或使用source关键字运行文件中的HQL
hive>source /path/to/file/withqueries.hql;
hive shell中甚至可以执行简单的操作系统shell命令,只需要在命令前加!
hive>! pwd;
Hive支持的数据类型
hive支持关系型数据库中的大多数基本数据类型,同时也支持三种集合数据类型,struct, map和array。需要注意的是所有这些数据类型都是对java中接口的实现,因此和java中的类型的行为是完全一致的。
struct — 例如某个列的数据为STRUCT {first STRING, last STRING}。可以通过字段名.first来引用第一个元素。
map — map用于存储key-value类型的数据,用字段名[‘key名’]来引用元素。
array — array中的元素必须是相同类型的,用数组名[index]来引用元素
在使用这些类型时,往往需要同时指定以下分隔符。例如对于map:
ROW FORMAT DELIMITED – 一行为一条记录
FIELDS TERMINATED BY ‘\t’ – 字段之间用tab分割
COLLECTION ITEMS TERMINATED BY ‘,’ – map中的不同key-value用逗号分割
MAP KEYS TERMINATED BY ‘:’; – key-value之间用冒号分割
对应的数据形式为:
$ cat test7.txt
1 job:80,team:60,person:70
2 job:60,team:80
3 job:90,team:70,person:100
Hive中的数据操作
Hive之所以被称为数据仓库,是因为数据仓库不需要实时响应查询,不需要记录级别的插入更新和删除。事实是,Hive的早期版本确实不支持行级插入操作,更新操作和删除操作,也不支持事务。新版本支持single-table transactions, 可以通过将table标记为transactional ,则支持insert, update和delete等ACID操作。否则只能在文件末尾append数据(HDFS的限制)。
而Hive支持ACID的实现原理是:
HDFS does not support in-place changes to files. It also does not offer read consistency in the face of writers appending to files being read by a user. In order to provide these features on top of HDFS we have followed the standard approach used in other data warehousing tools. Data for the table or partition is stored in a set of base files. New records, updates, and deletes are stored in delta files. A new set of delta files is created for each transaction (or in the case of streaming agents such as Flume or Storm, each batch of transactions) that alters a table or partition. At read time the reader merges the base and delta files, applying any updates and deletes as it reads.
向表导入数据有两种方式:
LOAD DATA LOCAL INPATH ‘/home/work/data/test7.txt’ INTO TABLE employee;
或使用查询语句插入数据
INSERT OVERWRITE TABLE employee
PARTITION (country = ‘US’, state = ‘OR’)
SELECT * FROM STAGED_EMPLOYEE se
WHERE se.cnty = ‘US’AND se.st = ‘OR’
hive会为每一个数据库创建一个目录,数据库中的表会以这个数据库目录的子目录形式存储。
hive对底层存储没有控制权,有很多其他的方式可以与数据进行创建,修改和破坏。因此hive不会在数据加载时进行验证,而是在查询时,也就是读时模式(schema on read)。如果模式和文件内容不匹配,hive会尽可能尝试将各种错误恢复过来。例如如果每行记录的字段个数少于定义的字段个数,用户将会看到查询结果中有很多null值;如果某些字段的实际值和定义的数据类型不一致,对于这些字段则会返回null值。还有必要时进行隐式的类型转换等。
分区表
与关系型数据库中的分区不同,Hive中的分区列不是表中的一个实际的字段,而是一个或者多个伪列。即表的数据文件中实际上并不保存分区列的信息与数据。例如:
create table partition_test
(member_id string,name string)
partitioned by (stat_date string,province string);
之后当向该表装载数据时,可指定装载入哪个分区:
INSERT OVERWRITE TABLE employee
PARTITION (country = ‘US’, state = ‘OR’)
SELECT * FROM STAGED_EMPLOYEE se
WHERE se.cnty = ‘US’AND se.st = ‘OR’
因此Hive无法检验数据是否放入了正确的分区。上面的HQL中,如果将条件改为se.cnty=‘china’,一样可以正常运行。
使用分区后,hive会创建相应的子目录并将数据放入子目录中,例如上例中,hive就会在表目录下创建/US子目录,以及/US/OR子目录。
在执行查询语句时,当where条件符合分区时,Hive仅扫描相应的子目录,因此分区最大的作用就是减少扫描的子目录以提高效率。
且一旦使用分区,分区字段就可以在HQL中使用,和字段没有什么区别。
当分区很多时,手动定义所有的分区会很麻烦,但动态分区可以解决这个问题:
INSERT OVERWRITE TABLE employee
PARTITION (country, state)
SELECT …, se.cnty, se.st FROM STAGED_EMPLOYEE se
自定义存储格式
Hive支持不同的存储格式,有TEXTFILE,SEQUENCEFILE,RCFILE,ORCFILE,其中TEXTFILE,SEQUENCEFILE为行存储,RCFILE为行列混合存储(record-columnar),ORCFILE为优化的行列混合存储(optimized-record-columnar)。表定义时使用“STORED AS”关键字来指定,不同的分区还可以使用不同的存储格式。
HQL
和SQL一样,HQL大小写无关。Hive支持大部分SQL操作符。
常见聚合函数:count,avg,sum, min, max
group by ,having与union all 和SQL里的用法完全相同。
order by 由于会有一个所有的数据都通过一个reducer进行处理的过程,所以对大数据集会很慢。另一个sort by 则会在每个reducer都执行一次局部排序,提高后面进行全局排序的效率。
支持inner join,left outer join, right outer join,full outer join ,cross join,left semi-join,但仅支持等值连接。
Hive还提供一类表生成函数,即将单列扩展成多列或者多行。
不支持如下形式的子查询:
select c1,c2 from t1
where c1 in (select c1 from t2)
但可以用left semi-join来替代:
SELECT c1,c2 from t1 left semi-join t2 on t1.c1=t2.c1;
支持如下嵌套查询
FROM ( SELECT c1,c2 FROM tableA WHERE c3=‘V3’)e
SELECT *
WHERE c1=‘V1’ and c2=‘V2’
这一节的最后展示如何用HQL实现大家熟知的word count处理:
CREATE TABLE docs (line STRING)
LOAD DATA INPATH ‘docs’ OVERWRITE INTO TABLE docs;
CREATE TABLE word_counts AS
SELECT word, count(1) AS count FROM
(SELECT explode(split(line,’\s’)) AS word FROM docs) w
GROUP BY word
ORDER BY word;
视图
和数据库中的视图类似。当一个查询引用一个视图时,这个视图定义的查询语句将和用户的查询语句组合在一起,然后由hive制定一个完整查询计划。
与关系型数据库中的视图不同的是,Hive中的视图不能做为insert或load命令的目标表。
索引
hive提供的索引功能有限。可以使用explain命令查看执行计划,确定是否使用了索引。Hive提供bitmap 索引和b-tree索引。
1.index的partition默认和数据表一致
2.视图上不能创建index
3. index可以通过stored as配置存储格式
Reducer
hive通过将查询划分成一个或多个MapReduce任务,每个任务都可能具有多个mapper或reducer,形成一个DAG图。确定最佳的mapper和reducer个数取决于多个变量,例如输入数据量大小以及对这些数据执行的操作。
hive根据输入数据量的大小来确定reducer的个数。可以修改
hive.exec.reducers.bytes.per.reducer属性 默认值1G,如果改为750MB就会直接增加reducer的个数。