Hive-学习总结
一.基础操作
1.1变量和属性
hivevar--(0.8以后版本) 用户自定义变量 (读写) ${hivevar:foo} --变量引用和替换
hiveconf --Hive相关的配置属性(读写)
system -- Java定义的配置属性(读写)
env -- Shell环境定义的环境变量(只可读)
在CLI中,可以使用SET命令显示或者修改变量值。
env命名空间可以作为Hive传递变量的一种方式,例如:
$ YEAR = 2012 hive -e "SELECT * FROM t1 WHERE year = ${env:YEAR}"
1.2 开启静默模式
两个用处,1.当我们使用CLI查询数据,不想显示“OK”或者查询时间等,可以使用-S开启静默模式,这样也可以将查询的结果直接输出或者重定向到文件中
hive -S -e "select * from t1" > /data/myquery
2.模糊查找某些属性
./hive -S -e "set" | grep warehouse hive.metastore.warehouse.dir=/user/hive/warehouse hive.warehouse.subdir.inherit.perms=true
1.3执行sql的两种方式
执行sql语句 hive -e "sql"
执行sql脚本 hive -f xxx.hql
通常我们约定使用src(代表源表)作为表名进行测试---源于Hive源码中的单元测试的写法,所以我们做测试前要创建一个src的表,同时必须至少有一行的数据在源表里面。
1.4 hiverc文件
CLI 选项中有 -i 文件名,这个选项允许用户指定一个文件,当CLI启动时,在提示符出现前会先执行这个文件。Hive会自动在HOME目录下寻找.hiverc文件,而且会自动执行这个文件中的命令。该文件中可以设置一些系统的属性或者增加对于Hadoop的分布式内存进行自定义的Hive扩展的Jar包。
1.5在hive中使用hadoop的dfs的命令
用户可以在hive CLi中执行hadoop命令,只需要将hadoop去掉就可以,这种方式实际上比其灯架的bash shell中执行的hadoop dfs更加高效,因为后者每次都会启动一个新的JVM实例,而Hive会在用一个进程中执行这些命令
二.数据类型和文件格式
2.1基本数据类型
TIMYINT 1byte
SMALLINT 2byte
INT 4byte
BIGINT 8vyte
BOOLEAN 布尔类型
FLOAT 单精度浮点数
DOUBLE 双精度浮点数
STRING 字符串,可以指定字符集,可以使用单、双引号
TIMESTAMP(v8.0+)整数、浮点数、字符串都可以,JDBC兼容的java.sql.Timestamp时间格式
BINARY (v8.0+)字节数组
需要注意的是,这些数据类型都是对Java接口的实现,所以具体细节和java中对应的类型都是完全一致的。
另外hive对字符串没有长度的限制,因为相比于其他SQL,hadoop和hive强调优化磁盘的读和写的性能,而不关注限制列的值的长度
新增数据类型TIMESTAMP的值可以时整数,也就是距离Unix新纪元时间的秒数,也可以是浮点数,即距离Unix新纪元的秒数,精确到纳秒(小数点后保留9位),还可以是字符串,即JDBC所约定的时间字符串格式,格式为YYYY-MM-DD hh:mm:ss.fffffffff
BINARY可以在记录中包含任意字节,这样可以防止Hive尝试作为数字,字符串等进行解析
注意:
不同的整型的值作对比,hive会都转成较大的类型再做比较
如果想将字符串类型的列转为数值类型,可以使用cast(s AS INT)
2.2集合数据类型
Hive中的列支持使用struct,map,array集合数据类型
struct -和c语言的struct或者对象类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT(first STRING,last STRING),那么访问第一个元素可以通过字段名.first来引用
struct('lijin','11')
map - 一组键值对的集合,使用数组表示法(['key'])可以访问元素
array - 一组相同类型和名称的变量的集合,可以用过数组元素的标号(['1'])访问元素
相比于传统的数据模型,不支持集合数据类型,因为这样破坏了标准格式,还会增加数据冗余的风险,但是可以提供更高吞吐量的数据,以最小的““头部寻址”来从磁盘上扫描数据相比于根据外键关联进行磁盘间的寻址操作,会提高性能。
2.3文本文件的数据编码
逗号分隔值CSV
制表符分隔值TSV
hive中默认的记录和字段分隔符
\n 对于文本文件来说,每一行都是一条记录,因此换行符可以分割记录
^A 用于分割字段,在CREATE TABLE 语句中可以使用八进制编码\001表示
^B 用于分割ARRAY 、STRACT中的元素,或用于MAP中键-值对之间的分割 \002表示
^C用于MAP中键-值之间的分割\003表示
2.4读时模式
传统数据库是写时模式(schema on write),即在数据写入数据库对模式进行检查
Hive不会再数据加载时进行验证,而是在查询时进行,也就是读时模式(schema on read)。
如果每行记录的字段个数少于对应的模式中定义的字段个数的话,少的部分都是null值
如果某些字段是数值类型的,但是hive读取时存在非数值类型的,将会返回null
三.数据操作
3.1向管理表中装载数据
LOAD DATA LOCAL INPATH "${env:HOME}/california-employees" OVERWRITE INTO TABLE employee PARTITION (country = 'US',state = 'CA')
如果分区目录不存在的话,这个命令会创建分目录,然后再将数据拷贝到分区目录下,如果目标表是分区表,那么语句应该省略PARTITION字句。
通常情况下指定的路径应该是一个目录,而不是单个独立的文件,而且文件名保持不变。
LOAD DATA LOCAL copy本地数据到位于分布式文件系统上的目标位置
LOAD DATA 数据在hdfs上,会移动到指定的目录下
OVERWRITE 重写 否则是追加,如果使用OVERWRITE关键字,会将原来的文件覆盖,如果不使用OVERWRITE,如果有同名的文件,会保留之前的文件并且会重命名文件尾“之前的文件名_序列号”(v0.8.0后支持)
3.2通过查询语句向表中插入数据
hive允许用户通过查询语句向目标表中插入数据
INSERT OVEROVERWRITE TABLE employee PARTITION (COUNTRY = 'US',state = 'OR') SELECT * FROM staged_employee se WHERE se.city = 'US' and se.st ='OR'
还可以一次扫描数据,按照多中方式进行划分
FROM staged_employee se INSERT OVERWRITE TABLE employees PARTITION (country = 'US',state = 'OR') SELECT * WHERE se.city = 'US' and se.state = 'OR' INSERT OVERWRITE TABLE employees PARTITION (country = 'US',state = 'CA') SELECT * WHERE se.city = 'US' and se.state = 'CA' ...
3.3动态分区插入
hive支持动态分区,通过查询的字段的值作为不同的分区,当然可以动态和静态分区混合使用,但是静态分区必须在动态分区之前。动态分区默认没有开启,开启后默认以“strict”模式执行,即至少有一个分区是静态的,有助于阻止因设计错误导致查询产生大量的分区。
hive.exec.dynamic.partition 默认值 false 设置为true,开启动态分区功能 hive.exec.dynamic.partition.mode 默认值 strict 即至少有一个分区是静态的 hive.exec.max.dynamic.partitions.pernode 默认值 100 每个mapper或reducer可以创建的最大动态分区个数。如果每个mapper或reducer创建更多的分区,会报错 hive.exec.max.dynamic.partitions +1000 一个动态分区可以创建的最大分区的个数 hive.exec.max.created.files 100000 全局可以创建的最大文件个数。有一个hadoop计数器会跟踪记录创建了多少个文件。
3.4单个查询语句中创建并加载数据
CREATE TABLE ca_employees AS SELECT name,salary,address FROM employees WHERE se.state = 'CA'
3.5导出数据
如果文件恰好是用户需要的格式,可以使用hadoop的cp命令进行copy
如果向从表中选取一部分字段,可以使用
INSERT OVERWRITE LOCAL DIRECTORY "/path" SELECT name,salary,address FROM employee WHERE se.state = 'CA'
还可以一次读取,按照多种格式导出多份数据
FROM staged_employees se INSERT OVERWRITE DIRECTORY '/path1' SELECT * WHERE se.city = 'US' and se.st= 'OR' INSERT OVERWRITE DIRECTORY '/path2' SELECT * WHERE se.city = 'US' and se.st= 'CA' ...