作者:Eeeddieee
工作中大部分时间都用到了Hive,虽然对Hive的架构、运行原理、调优方式有一定了解,但是很多都是在前人总结的基础上进行学习,没有自己的一套思考。比如往上很多资料都有说到Hive谓词下推,Hive引擎可以自动根据SQL语句进行优化,然后把各种谓词下推的SQL语句情况都列举出来,实际应用时只需要按照资料进行开发即可。随着对Hive使用时间的加长,对于这种被动的接收前人分析结论、经验的方式已经不能满足个人的求知欲了,再加上最近想写一个自动生成Hive SQL脚本的程序,了解了下Hive解析SQL的源码,感觉Hive源码里面也有很多东西可以去深挖的,所以就想系统的去研究下Hive源码。
因为在写Hive SQL脚本时,经常会配置一些参数,这些参数大部分都是前人总结出来的,我想能够系统、全面的了解下Hive的配置参数,所以就先从HiveConf类开始研究。本文内容可以收藏作为工具,往后有需要查看HiveConf类、Hive常用配置项时,直接翻阅查找即可。
HiveConf类继承自Hadoop的Configuration类,具有该类的特性,从这个角度也能看到Hive跟Hadoop的联系是比较密切的,Hive也可以很容易的获取到Hadoop的一些配置。
HiveConf类有39个属性,主要分为以下4类:
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | confVarByteArray | byte[] | ConfVar的字符数组,一个ConfVar就是一个配置项 |
2 | vars | HashMap |
配置项的Map集合,key是配置下·名称,value是配置项对象 |
3 | reverseMap | HashMap |
这个集合包含2套同样的配置,包含varname一组,altName重复添加,ConfVar的value都是一样的。另外在处理这个属性时还用到reverseMapLock来保证修改时的线程安全性 |
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | restrictList | ArrayList | 运行时拒绝修改的变量集合,包含hive in test、hidden list、restrictList、Internal varible、spark rsc conf list |
2 | hiddenSet | HashSet | 隐藏的配置列表:METASTOREPWD、HIVE_SERVER2_SSL_KEYSTORE_PASSWORD+S3 credentials相关配置 |
3 | rscList | ArrayList | Spark远程context配置,修改的话会导致新建spark session。HIVE_SPARK_RSC_CONF_LIST |
4 | metaVars | ConfVars[] | metastore相关的配置数组,当里面的配置修改时会重新建立hive cli |
5 | metaConfVars | ConfVars[] | 用户可以配置的metastore相关配置,包含try direct sql、ddl、partition name whitelist pattern |
6 | dbVars | ConfVars[] | 包含hadoop.bin.path、hive.metastore.warehouse.dir数据库存放位置、hive.exec.scratchdir运行时临时文件存放位置 |
7 | ENCODED_CONF | ConfVars[] | 加密的配置清单,目前只有queryString查询语句列表是加密的 |
8 | llapDaemonVarsSet | Set | llap进程相关设置,llap是long live and process的简称,是Hive 2.0新加的特性,可以让Hive程序长时间保持与Yarn的连接,达到减小启动次数、通信时间、资源复用的目的,从而提高效率。需要配置Tez引擎替换MR引擎。 |
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | origProp | Properties | HiveConf下所有properties,通过遍历所有ConfVars对象获取 |
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | hiveJar | String | jar包保存路径,读取的hadoop JobConf的job.jar路径(mapreduce.job.jar) |
2 | ausJars | String | hive.aux.jars.path下的所有jar包用分隔符,拼接成String,主要是找hive_cli.jar |
3 | hiveDefaultURL | URL | hive-default.xml位置的URL对象 |
4 | hiveSiteURL | URL | hive-site.xml位置的URL对象 |
5 | hivemetastoreSiteUrl | URL | hivemetastore-site.xml位置的URL对象 |
6 | hiveServer2SiteUrl | URL | hiveserver2-site.xml位置的URL对象 |
7 | loadMetastoreConfig | boolean | 是否开启远程元数据存储Metastore |
8 | loadHiveServer2Config | boolean | 是否加载hiveserver2-site.xml |
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | LOG | Log | slf4j 日志对象,用于记录日志 |
2 | isSparkConfigUpdated | boolean | 是否spark.开头的参数有进行修改更新 |
3 | LOG_PREFIX_LENGTH | int | 日志ID的长度,默认64位字符 |
4 | PREFIX_LLAP | String | llap.字符串,用于配置项前缀 |
5 | PREFIX_HIVE_LLAP | String | hive.llap.字符串,用于配置项前缀 |
6 | HIVE_LLAP_DAEMON_SERVICE_PRINCIPAL_NAME | String | 常量,写死hive.llap.daemon.service.principal配置项 |
7 | HIVE_SERVER2_AUTHENTICATION_LDAP_USERMEMBERSHIPKEY_NAME | String | 常量,写死hive.server2.authentication.ldap.userMembershipKey |
8 | daySet、hourSet、minuteSet、secondSet、milliSet、microSet、nanoSet | Hive中各种时间单位对应的字符串 |
方法分4大类:构造函数、常规Get/Set、功能方法、非常规GET/SET。重点讲下功能方法,其他的可获取思维导图查看。
关键的方法是:initialize方法, 他的作用是把所有配置项进行初始化。
序号 | 方法 | 方法功能说明 |
---|---|---|
1 | findConfigFile | 找Hive配置文件的URL地址HIVE_CONF_DIR=>HIVE_HOME拼接conf=>HiveConf.class的Jar包运行位置 |
2 | checkConfigFile | 检查文件是否Hive配置文件,并返回URL对象 |
3 | populateLlapDaemonVarsSet | 往传入的集合插入LlapDaemonVarsSet相关配置 |
4 | verifyAndSet | 检查配置是否允许在runtime修改,如果允许则配置为输入的value值 |
5 | isHiddenConfig | 检查配置是否是隐藏配置,不允许自定义参数 |
6 | isEncodedPar | 检查配置是否加密配置HiveConf.ENCODED_CONF |
7 | isSparkRelatedConfig | 检查是否sprak相关配置spark开头、yarn的spark.master |
8 | getDefaultTimeUnit | 获取默认时间单位 |
9 | toTime | 把数值跟旧单位转换成新单位的数值 |
10 | toSizeBytes | 把传进来的带单位字符串转换成数值(数值*单位) |
11 | parseNumberFollowedByUnit | 把带单位的字符串转换成数值+单位的数组 |
12 | unitFor | 根据传入字符串返回对应时间单位 |
13 | multiplierFor | 转换倍数,根据传入byte、kb、Mb、gb、tb,返回到byte对应的转换倍数 |
14 | stringFor | 根据传入的TimeUnit,返回对应单位的字符串 |
15 | isSparkDPPAny | 获取SPARK_DYNAMIC_PARTITION_PRUNING配置项的值 |
16 | logVars | 把所有配置项及值打印出来 |
17 | initialize | 关键方法:通过一些列步骤,初始化HiveConf类 |
18 | convertVarsToRegex | 把配置项转换成正则表达式,如hive.map=>hive\.map |
19 | applyDefaultNonNullConfVars | 把传入的conf对象的默认值设置好 |
20 | addToRestrictList | 把当前内容加入到restrictList中 |
21 | stripHiddenConfigurations | 删除隐藏配置值,有配置值的会置空 |
22 | isWebUiEnabled | 判断是否开启了WEBUI |
23 | isWebUiQueryInfoCacheEnabled | 判断是否开启了WEBUI查询语句缓存功能 |
24 | isSparkDPPAny | 判断是否开启了spark 动态分区 |
25 | isSparkDPPOnlyMapjoin | 判断SPARK_DYNAMIC_PARTITION_PRUNING、SPARK_DYNAMIC_PARTITION_PRUNING_MAP_JOIN_ONLY是否开启 |
26 | isLoadMetastoreConfig | 判断是否加载metastore配置 |
27 | generateMrDeprecationWarning | 生成mr引擎在未来将会弃用的警告 |
28 | verifyAndSetAll | 检查并配置所有参数(是否在运行时可修改) |
29 | subtree | 获取传入的参数开头对应的子树值,如传入spark,spark.map==>map |
HiveConf内部类有ConfVars枚举类、静态内部类StrictChecks、加解密相关类。
#### 4.1.1 类属性
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | 各种英文大写的枚举值 | 枚举 | 用于标识Hive的配置项,包含varname、defaultValue、Value等 |
2 | varname | String | 配置项名称,hive.map.xxx |
3 | altName | String | 配置项别名,hive.map.xxx |
4 | defaultExpr | String | 配置项默认正则表达式 |
5 | defaultStrVal、defaultIntVal、defaultLongVal、defaultFloatVal、defaultBoolVal | String | 配置项默认字符串、整数、长整数、浮点、布尔值 |
6 | valClass | Class> | 配置项的值的类 |
7 | valType | VarType | 配置项值的类型(内部枚举类VarType) |
8 | validator | Validator | |
9 | description | String | 配置项说明 |
10 | excluded | boolean | 是否剔除改项 |
11 | caseSensitive | boolean | 是否大小写敏感 |
各种英文大写的枚举值举例如下代码,其中大写英文为配置项名字,"hive.xxx"为varname,第二个引号为defaultStrVal等配置值,最后的比较长的英文描述为配置项的描述description:
SCRIPTWRAPPER("hive.exec.script.wrapper", null, ""),
PLAN("hive.exec.plan", "", ""),
STAGINGDIR("hive.exec.stagingdir", ".hive-staging",
"Directory name that will be created inside table locations in order to support HDFS encryption. " +
"This is replaces ${hive.exec.scratchdir} for query results with the exception of read-only tables. " +
"In all cases ${hive.exec.scratchdir} is still used for other temporary files, such as job plans."),
SCRATCHDIR("hive.exec.scratchdir", "/tmp/hive",
"HDFS root scratch dir for Hive jobs which gets created with write all (733) permission. " +
"For each connecting user, an HDFS scratch dir: ${hive.exec.scratchdir}/ is created, " +
"with ${hive.scratch.dir.permission}."),
REPLDIR("hive.repl.rootdir","/user/hive/repl/",
"HDFS root dir for all replication dumps."),
REPLCMENABLED("hive.repl.cm.enabled", false,
"Turn on ChangeManager, so delete files will go to cmrootdir.")
ConfVars枚举类内部也有定义一些常用方法,包含构造方法、Get/Set方法、功能类方法,主要看功能类方法可以了解到ConfVars类内部的一些操作。
序号 | 方法 | 方法功能说明 |
---|---|---|
1 | validate | 校验传入的value是否属于validator属性对象 |
2 | validatorDescription | 把validator属性对象转换成描述文字 |
3 | typeString | 获取valType的类型字符串 |
4 | toString | 把varname当作var对象的string输出 |
5 | findHadoopBinary | 找到hadoop bin文件夹路径 |
6 | findYarnBinary | 找到hadoop/yarn/bin文件夹路径 |
7 | findMapRedBinary | 找到hadoop/mpred/bin路径 |
8 | findHadoopHome | 找到HADOOP_HOME、HADOOP_PREFIX路径 |
9 | getValidStringValues | 获取校验后的参数值集合 |
ConfVars内部的VarType枚举类主要用于定义ConfVars的值的类型,包含STRING/INT/LONG/FLOAT/BOOLEAN。不在这里定义的类型都不能作为ConfVars的value。枚举类里面建了内部枚举类,这个有点意思。
类属性
序号 | 属性名 | 类型 | 含义 |
---|---|---|---|
1 | STRING | 枚举项 | String类型的值 |
2 | INT | 枚举项 | Int类型的值 |
3 | LONG | 枚举项 | long类型的值 |
4 | FLOAT | 枚举项 | float类型的值 |
5 | BOOLEAN | 枚举项 | boolean类型的值 |
类方法
序号 | 方法名 | 功能 |
---|---|---|
1 | checkType | 抽象方法,用于判断类型 |
2 | isType | 利用checkType判断配置的值是不是在5类中 |
3 | typeString | 枚举类的名称对应的字符串 |
4 | defaultValueString | 获取confVar.defaultExpr |
HiveConf类里面包含2静态块,1个用于初始化参数,1个用于设置metaStore相关Hive配置参数。
static {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = HiveConf.class.getClassLoader();
}
hiveDefaultURL = classLoader.getResource("hive-default.xml");
// Look for hive-site.xml on the CLASSPATH and log its location if found.
hiveSiteURL = findConfigFile(classLoader, "hive-site.xml", true);
hivemetastoreSiteUrl = findConfigFile(classLoader, "hivemetastore-site.xml", false);
hiveServer2SiteUrl = findConfigFile(classLoader, "hiveserver2-site.xml", false);
for (ConfVars confVar : ConfVars.values()) {
vars.put(confVar.varname, confVar);
}
Set<String> llapDaemonConfVarsSetLocal = new LinkedHashSet<>();
populateLlapDaemonVarsSet(llapDaemonConfVarsSetLocal);
llapDaemonVarsSet = Collections.unmodifiableSet(llapDaemonConfVarsSetLocal);
}
static {
for (ConfVars confVar : metaConfVars) {
metaConfs.put(confVar.varname, confVar);
}
}
经过查看HiveConf类的源码,我得到了以下几个方面的思考:
HiveConf源码里Hive配置项可以摘取,并分以下几类:
llapDaemonVarsSet:llap功能相关配置项的集合,以hive.llap开头。LLAP是hive 2.0.0版本引入的新特性,hive官方称为(Live long and process),将数据预取、缓存到基于yarn运行的守护进程中,降低和减少系统IO和与HDFS DataNode的交互。
keberos认证相关
序号 | varname | 功能 |
---|---|---|
1 | hive.llap.task.scheduler.am.registry.principal | am的注册协议,设置keberos |
2 | hive.llap.task.scheduler.am.registry.keytab.file | keytab文件的路径 |
3 | hive.llap.daemon.service.principal | llap后台进程的认证协议 |
4 | hive.llap.daemon.keytab.file | keytab文件路径 |
开启LLAP需要的配置
序号 | varname | 功能 |
---|---|---|
1 | hive.llap.execution.mode | 查询执行模式,有auto、none、all、map、only几个选项 |
2 | hive.llap.io.enabled | 是否开启llap ip功能 |
3 | hive.execution.mode | 设置查询试运行在container或者llap |
5 | hive.llap.daemon.memory.per.instance.mb | 单个llap执行executor的总内存 |
7 | hive.llap.zk.sm.connectionString | 连接zookeeper集群的连接串 |
8 | hive.llap.zk.registry.namespace | llap在zookeeper的路径 |
9 | hive.llap.zk.registry.user | llap登录zookeeper的用户名 |
运行资源配置相关
序号 | varname | 功能 |
---|---|---|
1 | hive.llap.daemon.yarn.container.mb | llap功能在yarn的container的内存大小,默认-1-无限制 |
2 | hive.llap.daemon.queue.name | llap功能的队列名 |
3 | hive.llap.daemon.vcpus.per.instance | 每一个llap实例的虚拟cpu核数 |
4 | hive.llap.daemon.num.executors | 每一个llap进程的executor数,默认是4,相当于并行度设置 |
Value隐藏加密的配置项HiddenConfig
序号 | varname | 功能 |
---|---|---|
1 | javax.jdo.option.ConnectionPassword | 连接的密码 |
2 | hive.server2.keystore.password | Hive Server2的密码 |
3 | S3 credentials相关配置 | AWS S3认证相关的配置 |
加密的参数:只有ENCODE_CONF,目前只有一个hive.query.string
Spark相关的配置(SparkReleatedConfig)
序号 | 说明 | 功能 |
---|---|---|
1 | spark开头的参数 | Spark相关配置 |
2 | yarn开头并且包含spark.master | Spark相关配置 |
3 | 在Spark rscList里面的配置项,请看上面的HiveConf类属性 | Spark相关配置 |
4 | mapreduce.job.queuename | 运行的队列,默认MR引擎也有这个 |
元素据相关配置metaConfs
序号 | varname | 功能 |
---|---|---|
1 | hive.metastore.try.direct.sql | 当需要读取大量分区、字段时可以开启这个减少读取时间 |
2 | hive.metastore.try.direct.sql.ddl | 跳过metaStore运行语句 |
3 | hive.metastore.client.socket.timeout | 超时时间,默认600s |
4 | hive.metastore.partition.name.whitelist.pattern | 分区正则白名单,匹配的的分区名称才能创建 |
5 | hive.metastore.client.capability.check | 是否开启metaStore的容量检查 |
6 | hive.metastore.disallow.incompatible.col.type.changes | 开启后禁止修改字段类型为另外一种不兼容的字段类型 |
系统相关配置集合ConfSystemProperties(主要是读取一些系统参数)
RestrictList:不允许在运行时修改的配置HIVE_CONF_RESTRICTED_LIST,hive.conf.restricted.list,包含以下配置:
"hive.security.authenticator.manager,hive.security.authorization.manager," +
"hive.security.metastore.authorization.manager,hive.security.metastore.authenticator.manager," +
"hive.users.in.admin.role,hive.server2.xsrf.filter.enabled,hive.security.authorization.enabled," +
"hive.distcp.privileged.doAs," +
"hive.server2.authentication.ldap.baseDN," +
"hive.server2.authentication.ldap.url," +
"hive.server2.authentication.ldap.Domain," +
"hive.server2.authentication.ldap.groupDNPattern," +
"hive.server2.authentication.ldap.groupFilter," +
"hive.server2.authentication.ldap.userDNPattern," +
"hive.server2.authentication.ldap.userFilter," +
"hive.server2.authentication.ldap.groupMembershipKey," +
"hive.server2.authentication.ldap.userMembershipKey," +
"hive.server2.authentication.ldap.groupClassKey," +
"hive.server2.authentication.ldap.customLDAPQuery," +
"hive.privilege.synchronizer," +
"hive.privilege.synchronizer.interval," +
"hive.spark.client.connect.timeout," +
"hive.spark.client.server.connect.timeout," +
"hive.spark.client.channel.log.level," +
"hive.spark.client.rpc.max.size," +
"hive.spark.client.rpc.threads," +
"hive.spark.client.secret.bits," +
"hive.spark.client.rpc.server.address," +
"hive.spark.client.rpc.server.port," +
"hive.spark.client.rpc.sasl.mechanisms," +
"bonecp.,"+
"hive.druid.broker.address.default,"+
"hive.druid.coordinator.address.default,"+
"hikari.,"+
"hadoop.bin.path,"+
"yarn.bin.path,"+
"spark.home",
RSCList,Spark Remote Client配置,修改以下任一项会导致重新建立一个spark session
序号 | varname | 功能 |
---|---|---|
1 | hive.spark.optimize.shuffle.serde | 是否进行shuffle优化 |
2 | hive.spark.client.future.timeout | 连接Spark的超时断开时间 |
序号 | 配置别名 | 说明 |
---|---|---|
1 | hiveDefaultURL | classLoader.getResource(“hive-default.xml”) |
2 | hiveSiteURL | 优先从HIVE_CONF_DIR找,没有就找HIVE_HOME/conf,还没有就找jar包的URI,再拼接/conf |
3 | hivemetastoreSiteUrl | hivemetastore-site.xml的位置 |
4 | hiveServer2SiteUrl | hiveserver2-site.xml的位置 |
5 | hiveJar | HIVEJAR,hive.jar.path,主要是找hive_cli.jar的位置 |
6 | auxjars | HIVEAUXJARS,hive.aux.jars.path,找Hive插件jar包的位置 |
动态分区相关
序号 | varname | 说明 |
---|---|---|
1 | hive.exec.dynamic.partition | 是否开启动态分区 |
2 | hive.exec.dynamic.partition.mode | 有严格和非严格模式,严格模式的话必须指定确认的分区 |
3 | hive.exec.max.dynamic.partitions | 最大动态分区数 |
本地模式相关
序号 | varname | 说明 |
---|---|---|
1 | hive.exec.mode.local.auto | 是否自动开启local模式,默认false。本地模式就是在本地执行任务,适用于数据量少的情况下减少网络传输及硬盘IO导致的消耗。 |
2 | hive.exec.mode.local.auto.inputbytes.max | 设置开启本地模式的数据大小,小于设置值时通过本地模式运行 |
mapjoin相关
序号 | varname | 说明 |
---|---|---|
1 | hive.ignore.mapjoin.hint | 是否忽略SQL语句里面的map join提示语法 |
2 | hive.mapjoin.bucket.cache.size(旧)/hive.smbjoin.cache.row(新) | 开启smbjoin时,小于多少开启MAP JOIN |
3 | hive.mapjoin.optimized.hashtable | mapjoin开启hashtable优化,只支持tez跟spark |
4 | hive.mapjoin.smalltable.filesize | 表大小小于多少时开启MAPJOIN,默认25Mb |
5 | hive.auto.convert.join | 是否开启自动MAP JOIN,默认true。跟smalltable.filesize设置有关 |
聚合相关
序号 | varname | 说明 |
---|---|---|
1 | hive.transpose.aggr.join | Join操作的同时进行聚合,默认FALSE.开启可能会对最终结果有影响 |
2 | hive.groupby.mapaggr.checkinterval | 分组字段达到多少行后进行聚合,默认100000 |
3 | hive.map.aggr | group by查询时是否开启map端聚合,默认true |
4 | hive.optimize.countdistinct | 是否转换count distinct为2个阶段,即先group by去重然后count。默认为true |
小文件相关
序号 | varname | 说明 |
---|---|---|
1 | hive.merge.tezfiles | tez的dag后面合并小文件 |
2 | hive.merge.sparkfiles | 合并spark任务的小文件 |
3 | hive.merge.size.per.task | 合并小文件任务的输出尺寸,默认256Mb |
4 | hive.merge.smallfiles.avgsize | 合并小文件的平均尺寸,默认16Mb |
5 | hive.merge.mapfiles | map only任务后面合并小文件,默认true |
6 | hive.merge.mapredfiles | 在map reduce任务后面合并小文件,默认true |
数据倾斜相关
序号 | varname | 说明 |
---|---|---|
1 | hive.groupby.skewindata | group by查询是否开启数据倾斜优化,默认false |
2 | hive.optimize.skewjoin | 是否进行数据倾斜优化,默认false。开启后当某key比较大时,会把相关数据存到hdfs然后开启另外一个mr去处理 |
3 | hive.skewjoin.key | 当key大于这个值时,认为是数据倾斜了.默认10万 |
4 | hive.optimize.skewjoin.compiletime | 利用元数据中的倾斜key,单独为倾斜key开启一个任务,然后其他key为第2个任务。最后2个任务结果用UNION合并起来。默认false |
桶、CBO跟分片
序号 | varname | 说明 |
---|---|---|
1 | mapreduce.input.fileinputformat.split.maxsize | 切片的最大文件大小 |
2 | mapreduce.input.fileinputformat.split.minsize | 切片的最小文件大小,跟maxSize,配合计算出切片数量 |
3 | hive.cbo.enable | 是否开启CBO(Cost Base Optimize)优化,默认true。 |
4 | hive.optimize.groupby | 在bucket表中用bucketed group by。默认true |
5 | hive.optimize.bucketmapjoin | 是否进行bucket map join,默认false |
6 | hive.optimize.bucketmapjoin.sortedmerge | 是否开启sortedmerge map join,默认false。需要2个join表都是分桶表,且桶内有进行排序 |
其他
序号 | varname | 说明 |
---|---|---|
1 | hive.spark.optimize.shuffle.serde | spark shuffle时启用序列化,可以减少shuffle的文件大小 |
2 | hive.query.timeout.seconds | 查询超过多少秒后失败 |
经过总结,主要有以下4点:
一个配置类必须要包含有系统必要的配置选项,否则就不能是一个配置类。
在实际编码中如何获取配置文件呢?
其中通过jar包运行位置去查找的代码如下:
HiveConf.class.getProtectionDomain().getCodeSource().getLocation();
jarUri = sourceUrl.getProtocol().equalsIgnoreCase("jar") ? new URI(sourceUrl.getPath()) : sourceUrl.toURI();