hive需要一个存放元数据的数据库,如果用mysql,那么记住把mysql的jdbc的jar文件放到hive的lib目录下面,

如果没有放,在创建hive表的时候就会有错误:

FAILED:Errorinmetadata:javax.jdo.JDOFatalInternalException

Hadoop文件的路径是放在元数据库里, DBS和SDS表里,而不是在什么参数文件里。 如果你改了hadoop主机名或者端口,就要手工修改这些表里的内容,update语句一句句运行,表多的话比较麻烦。不知道有没有什么简单一点的方法可以改。


在创建externaltable的时候,注意LOCATION后面跟的参数是目录名而不是文件名,数据表文件都在此目录下。如果创建时候报错说FileNotFoundException某个东东isnotadirectory,那么多半是把文件名当参数了。


.hiverc文件,hive客户端启动是会在$HOME里找这个文件,可以在里面放一些常用的设置命令。(这里面放的是hive命令,而不是linuxshell命令)

推荐的设置比如:

sethive.exec.mode.local.auto=true;这个会让hive尽量尝试local模式查询而不是用mapred方式。

hive.mapjoin.smalltable.filesize=25000000,这个25M是默认值,就是小于这个数值的表会放在各主机的cache里,做MAPsideJOIN

如果要hive做mapsidejoin,sethive.auto.convert.join=true;



可以在hive客户端里运行hadoopdfs命令,只要去掉hadoop

hive>dfs-ls/;

即可

如果要查询结果里显示列名,默认是不显示的,要这样:

sethive.cli.print.header=true;

select*formsometable;

这样结果就有列标题了。

如果希望总是这样显示,就把这句放到.hiverc里面。


hive的脚本,hql文件里,注释行是以--开头,


hive的数据类型,基本的有:

tinyintsmallintINTBIGINTBOOLEANFLOATDOUBLESTRING

TIMESTAMP,这个可以是整数,浮点数(精确到纳秒)或字串。

BINARY

如果一定要比较两个不同的数据类型字段,用cast,比如:

cast(sASINT)

另外,支持复杂的数据类型,有:

structmaparray

你可以在表里用这些复杂类型,比如

subordinatesARRAY,

分隔符,hive表用的分隔符比较特殊:

^A分隔字段在HQL里面用反斜杠001引用

^B分隔ARRAYSTRUCT里的元素反斜杠002

^CfengeMAP里的键和值反斜杠003


ROWFORMATDELIMITED

有时候在定义表的语句里会有这么一条,这主要是你要用自己定义的字段分隔符时,需要这一句。注意行分隔符总是反斜杠n,不能自定义的。


hive的PARTITION,这个东西看下来,似乎是这样。PARTITION里的列并不在定义表内容里面,而是在PARTITION后面的括号里定义,但是查询的时候又可以把它当列来查询。

hive存储时会按PARTITION键值创建目录,吧相应的数据放在目录里。如果是外部表,要求它们已经安装PARTITION键值分好了目录?

比如:

ALTERTABLElog_messagesADDPARTITION(year=2012,month=1,day=2)

LOCATION'hdfs://master_server/data/log_messages/2012/01/02';

创建这个log_messages外部表的时候,没有用LOCATION定义路径,也不需要定义,而是后来用ADDPARTITOON的办法把分区一个一个加进去。


注意hive的LOADDATA命令,只是简单的拷贝本地数据到hive的表,如果本地数据的分隔符和hive默认不一致,你就要在创建表的时候就定义好分隔符。

如果测试的时候,你没有定义特殊分隔符,那你如果要在本地文本文件里键入^A这样的控制符,就要用到vi的hex模式。

:%!xxd进入HEX模式,:%!xxd-r推出HEX模式。

hive是没有行级别的insert语句的,表内容都是大批量导入

比如:

INSERTOVERWRITETABLEemployees
PARTITION(country='US',state='OR')
SELECT*FROMstaged_employeesse
WHEREse.cnty='US'ANDse.st='OR';

或者是LOADDATA命令:

LOADDATALOCALINPATH'${env:HOME}/california-employees'
OVERWRITEINTOTABLEemployees
PARTITION(country='US',state='CA');

hive数据导出到本地文件,也是INSERT命令

INSERTOVERWRITELOCALDIRECTORY'/tmp/ca_employees'
SELECTname,salary,address
FROMemployees
WHEREse.state='CA';

或者如果是要导出多个查询的结果:

FROMstaged_employeesse
INSERTOVERWRITEDIRECTORY'/tmp/or_employees'
SELECT*WHEREse.cty='US'andse.st='OR'
INSERTOVERWRITEDIRECTORY'/tmp/ca_employees'
SELECT*WHEREse.cty='US'andse.st='CA'
INSERTOVERWRITEDIRECTORY'/tmp/il_employees'
SELECT*WHEREse.cty='US'andse.st='IL';


JOIN操作时,hive默认认为最右边的表是最大的,尽量把左边的表缓存起来。所以写JOIN语句时注意顺序。

还有一种优化方法是在join的时候过滤:

SELECTs.ymd,s.symbol,s.price_close,d.dividendFROM
(SELECT*FROMstocksWHEREsymbol='AAPL'ANDexchange='NASDAQ')s
LEFTOUTERJOIN
(SELECT*FROMdividendsWHEREsymbol='AAPL'ANDexchange='NASDAQ')d
ONs.ymd=d.ymd;


LEFTSEMIJOIN,这种是查询左边的表在右边表里能找到对应记录的记录,因为hiveQL不支持IN

所以才有这个半join,右边的表里的列是不能select的。并且没有RIGHTSEMIJOIN


结果的排序,ORDERBY是对结果全排序,所有的结构都送到一个reducer,时间很长。

SORTBY只在各个reducer内部排序。


优化设置:


hive.exec.parallel
true

Whethertoexecutejobsinparallel

这个设置是如果有可以并行的stage,则尽量并行执行这些stage

sethive.mapred.mode为strict,这有三大作用:

1如果有partition的话,必须在查询是为partition设置好过滤条件

2ORDERBY的话必须有LIMIT,因为ORDERBY是只在一个reducer上面排序

3禁止笛卡尔连接,对于tableAJOINtableBWHEREA.id=B.id,这样的查询句子,hive会做一个dikaer连接,这在设为strict时候就不允许运行。

mapred.job.reuse.jvm.num.tasks

这个参数是一个JVM允许运行几个任务,可多设计个,避免多次启动JVM的开销。

还有一个实际上是hadoop的参数,控制每个datanode可以打开的文件数:


dfs.datanode.max.xcievers
8192


压缩,BZIP和LZO都是可分割的压缩算法,就是说hive知道米的记录的边界在哪里。


*中间压缩,mapred计算的中间值,可以用压缩减少网络压力。

hive.exec.compress.intermediate
true
ThiscontrolswhetherintermediatefilesproducedbyHivebetween
multiplemap-reducejobsarecompressed.Thecompressioncodecandotheroptions
aredeterminedfromhadoopconfigvariablesmapred.output.compress*


压缩有其默认算法,如果要修改,就要修改hadoop的参数:

mapred.map.output.compression.codec
org.apache.hadoop.io.compress.SnappyCodec

可以在mapred-site或者hive-site文件里设。


*输出的压缩

hive.exec.compress.output
false

改true打开这个特性


*表的存储,可以采用suquencefile,而不是文本文件,这样在压缩存储的情况下依然可以分割。

CREATETABLEa_sequence_file_tableSTOREDASSEQUENCEFILE;

而一般的创建语句是这样

CREATETABLEintermediate_comp_onROWFORMATDELIMITEDFIELDSTERMINATEDBY'\t'

要创建压缩的sequence存储表,可以这样

setmapred.output.compression.type=BLOCK;然后

sethive.exec.compress.output=true;然后

setmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;再建表

CREATETABLEfinal_comp_on_gz_seqROWFORMATDELIMITEDFIELDSTERMINATEDBY'\t'
STOREDASSEQUENCEFILE
ASSELECT*FROMa;

Gzip本来是不可分割的,但是用了sequence,就可以按BLOCK分割。



一个奇怪的报错,

有一次用hue的beewax界面创建一个表,用的命令是: create 表名 as select  。。。。。

的时候立即报错,查log说是你必须是superuser才行,搞得莫名其妙。

然后干脆ssh进去用命令行的hive创建表,

这次的报错是:

FAILED: SemanticException 0:0 Error creating temporary folder on: hdfs://master:8020/user/hive/warehouse.
Error encountered near token 'TOK_TMP_FILE'

一开始感到摸不着头脑,后来仔细看看原来select里面一个表的字段写错了,改正以后就一切正常。

这个错误信息比较误导啊,不过如果你只看SementicException这个单词应该也可以猜出是语句写错了。。。