你可以在任何Drill集群上,为查询处理的Drillbit进程,配置直接内存的大小。Drillbit进程默认的内存大小是8G,但是Drill推荐根据负载大小,设置16G及以上的内存。Drillbit进程分配给查询操作的直接内存大小不能超过这个参数值。

这里插入一下“直接内存”的释义:

直接内存不是jvm运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但是这部分内存也被频繁的使用,而且也可能导致OutOfMemoryError的异常出现。

在jdk1.4中新加入了NIO类,引入了一直基于通道和缓存区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里的DirectByteButter对象作为这块内存的引用进行操作。这样在一些场景中可以显著提高性能,因为避免了在java堆里和Native堆里来回复制数据。

显然,本机直接内存的分配不会受java堆内存大小的限制,但是,既然也是内存,则肯定还是会受到本机总物理内存大小及处理器寻址空间的限制。所以在配置jvm虚拟机参数时,一般会根据实际物理内存来设置-Xmx,-Xms等参数信息,但经常会忽略掉直接内存,使得jvm各个内存区域的和大于物理内存限制,从而导致动态扩展时出现OutOfMemeryError异常。

Drill使用java直接内存,通常在内存中执行操作,相比于在磁盘上操作,效果要好。不像MapReduce在一个工作的每个阶段都会写磁盘,除非绝对需要,Drill通常不写数据到磁盘上。

Jvm的堆内存不限制Drillbit进程的直接内存大小,Drill的非堆内存一般设置为4-8G(默认是4G),通常这已经足够,因为Drill避免数据存放在堆中。

Drill 1.5后,使用了一个新的收集器,可以提高操作使用直接内存的效率,并可以更准确的追踪内存的变化。基于这种变化,排序操作(早期版本查询可以运行成功)可能会因为内存不足,导致查询失败和内存溢出错误,而非溢写到磁盘上。

planner.memory.max_query_memory_per_node这个系统选型,可以设置在每个节点上的一次查询中,可以分配给排序操作的最大直接内存。

如果一个查询计划包含多个排序操作,它们共享这部分内存。如果你运行了包含排序操作的查询,出现了内存错误,可以试试增加这个参数的值。如果增加此值,你扔碰到内存错误,你可以减少planner.width.max_per_node所设置的值,从而减少每个节点的系统并发度。但是,这通常会增加查询完成的时间。

修改 Drillbit 的内存值

你可以在集群中修改每一个Drillbit节点的内存值,为了达到这个目的,可以在Drillbit的启动脚本drill-env.sh中(位于/conf下),设置DRILL_MAX_DIRECT_MEMORY变量,如下:

export DRILL_MAX_DIRECT_MEMORY=${DRILL_MAX_DIRECT_MEMORY:-“”}
注意:如果这个参数未设置,大小限制取决于实际可用的系统内存。
修改完 drill-env.sh后,记得重启每台节点上的Drillbit进程以使其生效。

关于Drillbit启动脚本

在drill-env.sh文件中包含以下的选项:

export DRILL_HEAP=${DRILL_HEAP:-"4G"}

export DRILL_MAX_DIRECT_MEMORY=${DRILL_MAX_DIRECT_MEMORY:-"8G"}

DRILL_MAX_HEAP 是每个节点上JVM理论上的堆最大值。
DRILL_MAX_DIRECT_MEMORY是每个节点java直接内存的最大值。

如果性能是一个问题,可以添加-Dbounds=false, 如下所示:
export DRILL_JAVA_OPTS=”$DRILL_JAVA_OPTS -Dbounds=false”

引用列表:
1. https://drill.apache.org/docs/configuring-drill-memory/
2. http://2387209.blog.51cto.com/2377209/1508621

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐