CarbonData调优思路
查询性能调优
- Spark Executor数量:Executor是Spark并行性的基础实体。通过增加Executor数量,集群中的并行数量也会增加。关于如何配置Executor数量,请参考Spark资料。
- Executor核:每个Executor内,并行任务数受Executor核的配置控制。通过增加Executor核数,可增加并行任务数,从而提高性能。
- HDFS block容量:CarbonData通过给不同的处理器分配不同的block来分配查询任务。所以一个HDFS block是一个分区单元。另外,CarbonData在Spark驱动器中,支持全局block级索引,这有助于减少需要被扫描的查询block的数量。设置较大的block容量,可提高I/O效率,但是会降低全局索引效率;设置较小的block容量,意味着更多的block数量,会降低I/O效率,但是会提高全局索引效率,同时,对于索引查询会要求更多的内存。
- 扫描线程数量:扫描仪(Scanner)线程控制每个任务中并行处理的数据块的数量。通过增加扫描仪线程数,可增加并行处理的数据块的数量,从而提高性能。可使用“carbon.properties”文件中的“carbon.number.of.cores”属性来配置扫描仪线程数。例如,“carbon.number.of.cores = 4”。
- B-Tree缓存:为了获得更好的查询特性,可以通过B-tree LRU(least recently used,最近最少使用)缓存来优化缓存内存。在driver中,B-Tree LRU缓存配置将有助于通过释放未被访问或未使用的表segments来释放缓存。类似地,在executor中,B-Tree LRU缓存配置将有助于释放未被访问或未使用的表blocks。具体可参考表2中的参数“carbon.max.driver.lru.cache.size”和“carbon.max.executor.lru.cache.size”的详细描述。
CarbonData查询流程
当CarbonData首次收到对某个表(例如表A)的查询任务时,系统会加载表A的索引数据到内存中,执行查询流程。当CarbonData再次收到对表A的查询任务时,系统则不需要再加载其索引数据。
在CarbonData中执行查询时,查询任务会被分成几个扫描任务。即,基于CarbonData数据存储的HDFS block对扫描任务进行分割。扫描任务由集群中的执行器执行。扫描任务可以并行、部分并行,或顺序处理,具体采用的方式取决于执行器的数量以及配置的执行器核数。
查询任务的某些部分可在独立的任务级上处理,例如select和filter。查询任务的某些部分可在独立的任务级上进行部分处理,例如group-by、count、distinct count等。
某些操作无法在任务级上处理,例如Having Clause(分组后的过滤),sort等。这些无法在任务级上处理,或只能在任务级上部分处理的操作需要在集群内跨执行器来传输数据(部分结果)。这个传送操作被称为shuffle。
任务数量越多,需要shuffle的数据就越多,会对查询性能产生不利影响。
由于任务数量取决于HDFS block的数量,而HDFS block的数量取决于每个block的大小,因此合理选择HDFS block的大小很重要,需要在提高并行性,进行shuffle操作的数据量和聚合表的大小之间达到平衡。
分割和Executors的关系
如果分割数小于等于Executor数乘以Executor核数,那么任务将以并行方式运行。否则,某些任务只有在其他任务完成之后才能开始。因此,要确保Executor数乘以Executor核数大于等于分割数。同时,还要确保有足够的分割数,这样一个查询任务可被分为足够多的子任务,从而确保并行性。
配置扫描仪线程
扫描仪线程属性决定了每个分割的数据被划分的可并行处理的数据块的数量。如果数量过多,会产生很多小数据块,性能会受到影响。如果数量过少,并行性不佳,性能也会受到影响。因此,决定扫描仪线程数时,需要考虑一个分割内的平均数据大小,选择一个使数据块不会很小的值。经验法则是将单个块大小(MB)除以250得到的值作为扫描仪线程数。
增加并行性还需考虑的重要一点是集群中实际可用的CPU核数,确保并行计算数不超过实际CPU核数的75%至80%。
CPU核数约等于:
并行任务数x扫描仪线程数。其中并行任务数为分割数和执行器数x执行器核数两者之间的较小值。
数据加载性能调优
数据加载性能调优与查询性能调优差异很大。跟查询性能一样,数据加载性能也取决于可达到的并行性。在数据加载情况下,工作线程的数量决定并行的单元。因此,更多的执行器就意味着更多的执行器核数,每个执行器都可以提高数据加载性能。
同时,为了得到更好的性能,可在HDFS中配置如下参数。
参数 |
建议值 |
---|---|
dfs.datanode.drop.cache.behind.reads |
false |
dfs.datanode.drop.cache.behind.writes |
false |
dfs.datanode.sync.behind.writes |
true |
压缩调优
CarbonData结合少数轻量级压缩算法和重量级压缩算法来压缩数据。虽然这些算法可处理任何类型的数据,但如果数据经过排序,相似值在一起出现时,就会获得更好的压缩率。
CarbonData数据加载过程中,数据基于Table中的列顺序进行排序,从而确保相似值在一起出现,以获得更好的压缩率。
由于CarbonData按照Table中定义的列顺序将数据进行排序,因此列顺序对于压缩效率起重要作用。如果低cardinality维度位于左边,那么排序后的数据分区范围较小,压缩效率较高。如果高cardinality维度位于左边,那么排序后的数据分区范围较大,压缩效率较低。
内存调优
CarbonData为内存调优提供了一个机制,其中数据加载会依赖于查询中需要的列。不论何时,接收到一个查询命令,将会获取到该查询中的列,并确保内存中这些列有数据加载。在该操作期间,如果达到内存的阈值,为了给查询需要的列提供内存空间,最少使用加载级别的文件将会被删除。