hive報錯: Specified key was too long; max key length is 767 bytes
DataNucleus.Datastore (Log4JLogger.java:error(115)) - An exception was thrown while adding/validating class(es) : Specified key was too long; max key length is 767 bytes
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Specified key was too long; max key length is 767 bytes
然後在全網搜索,幾乎所有的文章都沒正面講原因(不好意思,這裏用了誇張的手法,如果有說錯的,還請見諒),要麽就是臭長臭長的,很難受。
還有一個東西提一下,就是hive在控制臺打印的報錯信息是這樣子的:
ERROR [main]: metastore.RetryingHMSHandler (RetryingHMSHandler.java:invoke(150)) - HMSHandler Fatal error: javax.jdo.JDODataStoreException: Error(s) were found while auto-creating/validating the datastore for classes. The errors are printed in the log, and are attached to this exception.
說實話,第一段很好判斷,其實就是mysql的字符集編碼的問題(所實話,這是一個很大的問題,後面慢慢解釋),然後第二段報錯是控制臺打印的,只能夠看出報錯是因為在創建/插入/更新某個數據的數據出現了異常。
所以從這裏告訴我們一個道理:出現報錯去看log日誌好嗎?????
Hive中的日誌分為兩種
1. 系統日誌,記錄了hive的運行情況,錯誤狀況。
2. Job 日誌,記錄了Hive 中job的執行的歷史過程。
系統日誌存儲
在${HIVE_HOME}/conf/hive-log4j.properties 文件中記錄了Hive日誌的存儲情況 重命名hive-log4j.properties.template hive-log4j.properties
默認的存儲情況:$
hive.root.logger=WARN,DRFA
hive.log.dir=/tmp/${user.name} # 默認的存儲位置是/tmp這個臨時目錄(這個目錄就好像Windows的回收站)
hive.log.file=hive.log # 默認的文件名
可以修改到
hive.log.dir=/user/apache-hive-1.2.1-bin/log/${user.name}
hive.log.file=hive.log
Hive的Job日誌存儲
//Location of Hive run time structured log file
HIVEHISTORYFILELOC("hive.querylog.location", "/tmp/" + System.getProperty("user.name")),
默認存儲與 /tmp/{user.name}目錄下。
通過如上的修改,再次生成的hive日誌文件,就會在你自己指定的目錄中了
扯遠了,言歸正傳!!
所以通過以上的亂七八糟的東西,我們就確定了報錯,是mysql中hive的元數據庫的字符集問題,也正是因為字符集問題,導致了create或者insert或者load等等操作出現了問題!
1、如果有興趣和心思,大家可以先研究明白mysql的字符集都有哪些地方是可以設置的。
2、如果沒有,那請看接下來鄙人講的東西。
原因分析:
-1.mysql數據庫創建數據庫的時候的字符集默認是latin1,很有可能之前被修改過,改成UTF8或者其他
如何查看?
註:這裏的a這個庫,是我的hive的元數據信息的庫
如果是如上的這張圖,那麽a這個數據庫的字符集就是utf-8,並且如果hive在這個庫裏面生成的相關元數據信息表,這些表也都會是utf-8的字符集!不信你看!
你會發現這裏的所有表甚至表中的字段都是utf-8的字符集,並且當你在操作hive的時候,那麽就很有可能會出現標題上的錯誤!
-2.然後你就會去百度,搜索各種各樣的文章,發現可以這麽修改數據庫的字符集
alter database a character set latin1;
這裏順便提一句:
//修改數據庫
alter database 數據庫名 character set utf8;
//修改表
alter table 表名 convert to character set gbk;
//修改字段
alter table 表名 modify column ‘字段名‘ varchar(30) character set gbk not null;
//添加表字段
alter table 表名 add column ‘字段名‘ varchar (20) character set gbk;
天真的你發現,已經完全修改過來了,應該不會有問題了!
-3.然而這時候,你重啟了你的環境(包括重啟虛擬機一大堆雜七雜八的操作),打開hive,發現該報錯的還是報錯!
-4.為什麽呢,你可以嘗試下看看元數據庫裏的表的字符集有改變嗎?
-5.所以問題已經很明顯了,這樣修改雖然數據庫的字符集改了,但是其中表的字符集和字段都沒改過來
解決:
關於如何解決這個問題網上的說法很多很雜,這裏做一些整理
-1.將原來那個元數據信息庫刪除
drop database a;
-2.手動創建一個空的數據庫
create database metastore character set latin1;
或者可以先創建:create database metastore
然後在alter修改字符集
-3.在hive-site.xml中配置
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://bigdata-01:3306/metastore?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
-4.然後再去開啟hive,如果能正常開啟就接著看下一步,如果不行,一定記得看hive的log日誌
-5.如果成功了,請記得一定要去mysql中查看metastore中任意一張表的元數據信息
-6.如果你發現表中的元數據信息是latin1,那麽你的hive操作就不會報Specified key was too long; max key length is 767 bytes,這樣問題就解決了!
轉自https://blog.csdn.net/lsr40/article/details/79422718
hive報錯: Specified key was too long; max key length is 767 bytes