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内部排序。
优化设置:
这个设置是如果有可以并行的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可以打开的文件数:
压缩,BZIP和LZO都是可分割的压缩算法,就是说hive知道米的记录的边界在哪里。
*中间压缩,mapred计算的中间值,可以用压缩减少网络压力。
multiplemap-reducejobsarecompressed.Thecompressioncodecandotheroptions
aredeterminedfromhadoopconfigvariablesmapred.output.compress*
压缩有其默认算法,如果要修改,就要修改hadoop的参数:
可以在mapred-site或者hive-site文件里设。
*输出的压缩
改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这个单词应该也可以猜出是语句写错了。。。