常用技巧
本教程将指导你如何创建 CarbonData 表以及进行性能优化。
以下章节将详细介绍下面的主题:
创建 CarbonData 表的建议
比如,下面总结了行数范围在 10000 到 100 亿以及列数在 100 到 300 表格的创建分析结果。
下表介绍了使用到的一些列。
表格列说明
列名 |
数据了下 |
基数 |
属性 |
msisdn
String
30 million
Dimension
BEGIN_TIME
BigInt
10 Thousand
Dimension
HOST
String
1 million
Dimension
Dime_1
String
1 Thousand
Dimension
counter_1
Decimal
NA
Measure
counter_2
Numeric(20,0)
NA
Measure
counter_100
Decimal
NA
Measure
把经常使用到的过滤列放在开头
比如, MSISDN 在大多数查询会用来过滤,这样我们必须将 MSISDN 放在第一列。
create table 命令可以按照以下建议进行修改:
create table carbondata_table(
msisdn String,
BEGIN_TIME bigint,
HOST String,
Dime_1 String,
counter_1, Decimal
...
)STORED BY 'carbondata'
TBLPROPERTIES ('SORT_COLUMNS'='msisdn, Dime_1')
现在使用 MSISDN 进行过滤的查询效率会更高。
将列按照使用频率从低到高的次序排列
如果指定查询中用到的表有多个频繁用于过滤结果的列,建议将列按照使用频率从低到高的次序排列。
经常使用的列按照这种次序排序,可以提高压缩比并提高在这些列上筛选结果的查询性能。
比如, 如果 MSISDN、HOST 和 Dime_1 是经常使用的列,那么列的顺序建议为 Dime_1>HOST>MSISDN,因为 Dime_1 使用频率最低。
create table 命令可以按照以下建议进行修改:
create table carbondata_table(
msisdn String,
BEGIN_TIME bigint,
HOST String,
Dime_1 String,
counter_1, Decimal
...
)STORED BY 'carbondata'
TBLPROPERTIES ('SORT_COLUMNS'='Dime_1, HOST, MSISDN')
对于精度不高的测量类型的列,请将 Numeric(20,0)数据类型替换为 Double 数据类型
对于测量类型(measure type)的列,不要求高精度,建议用 Double 替换数字数据类型以增强查询性能。
create table 命令可以按照以下建议进行修改:
create table carbondata_table(
Dime_1 String,
BEGIN_TIME bigint,
END_TIME bigint,
HOST String,
MSISDN String,
counter_1 decimal,
counter_2 double,
...
)STORED BY 'carbondata'
TBLPROPERTIES ('SORT_COLUMNS'='Dime_1, HOST, MSISDN')
测试用例的性能分析结果显示查询执行时间从 15 秒缩短到 3 秒,因此将性能提高了近 5 倍。
增量字符的列应重新排列在维度(dimensions)的末尾
考虑每天加载数据的场景,每次加载 begin_time 都是增加的,建议将 begin_time 放在维度的末尾。
增量值在使用最小/最大索引时很有效。create table 命令可以按照以下建议进行修改 :
create table carbondata_table(
Dime_1 String,
HOST String,
MSISDN String,
counter_1 double,
counter_2 double,
BEGIN_TIME bigint,
END_TIME bigint,
...
counter_100 double
)STORED BY 'carbondata'
TBLPROPERTIES ('SORT_COLUMNS'='Dime_1, HOST, MSISDN')
海量数据加载性能优化的配置
CarbonData 支持加载海量数据,在这个过程中,加载时排序数据会消耗大量的内存和磁盘IO,有时候可能出现内存不足异常。
如果你没有足够的内存可使用,那么你可能更喜欢减慢数据的加载速度,而不是数据加载失败。
你可以通过调整 carbon.properties 文件中的属性来配置 CarbonData 以便获得更好的性能。
属性 |
默认值 |
说明/调整 |
carbon.number.of.cores.while.loading
默认值: 2. 这个值应该 >= 2
数据加载时所用到核的个数。
carbon.sort.size
默认值: 100000. 这个值应该 >= 100.
加载数据时在排序步骤中写入本地文件的阈值
carbon.sort.file.write.buffer.size
默认值: 50000.
DataOutputStream 缓存。
carbon.number.of.cores.block.sort
默认值: 7
如果你有足够的内存和 CPU,建议加大这个设置。
carbon.merge.sort.reader.thread
默认值: 3
读取中间文件进行最终合并的最大线程数。
carbon.merge.sort.prefetch
默认值: true
如果你没有足够的内存,建议将它设置为 false。
比如,我们仅仅只有 16 个核,64GB 内存,但是有1000万条记录需要导入到 CarbonData 表中。使用默认配置总是在排序阶段失败,建议按照如下配置修改 carbon.properties:
carbon.number.of.cores.block.sort=1
carbon.merge.sort.reader.thread=1
carbon.sort.size=5000
carbon.sort.file.write.buffer.size=5000
carbon.merge.sort.prefetch=false
CarbonData 性能优化的配置
最近我们在金融和电信领域使用 CarbonData 做了一些性能测试。它涉及详细的查询和聚合场景。影响性能的配置已经被确定,并归纳到以下表中 :
属性 |
位置 |
使用场景 |
模式 |
训练 |
carbon.sort.intermediate.files.limit
spark/carbonlib/carbon.properties
数据加载
在数据加载时,排序过程中会用到一些中间文件。这个数字指定启动合并排序时需要的最小中间文件个数。
将此值设置的更高有助于提高加载的性能。比如,当我们将这个值从 20 设置成 100,数据加载性能从 35MB/S 提高到超过 50MB/S。这个值越大,数据加载期间使用到的内存越多。
carbon.number.of.cores.while.loading
spark/carbonlib/carbon.properties
数据加载
指定在 CarbonData 加载数据期间用于数据处理的内核数量。
如果你有很多的 CPU,那么你可以增加 CPUs 的个数,这将会提升性能。比如我们将这个值从 2 设置成 4,那么 CSV 的读性能提高大约一倍。
carbon.compaction.level.threshold
spark/carbonlib/carbon.properties
数据加载和查询
对于 minor compaction,指定阶段 1 要合并分段的数量和阶段 2 要合并的压缩分段的数量。
每个 CarbonData 加载进程将会创建一个分段,如果每个加载进程生成的文件都很小,则会在一段时间内生成很多小文件,从而影响查询性能。配置这个参数会把小的段合并成一个大的段,它将对数据进行排序并提高性能。比如在电信的场景里,minor compaction 之后性能提高了 2 倍以上。
spark.sql.shuffle.partitions
spark/conf/spark-defaults.conf
查询
Spark 洗牌是启动任务的个数。
这个值可以设置成 executor 核总数的 1 到 2倍。在一个聚合场景里,将这个值从 200 减少到 32,查询时间从 17 秒减少到 9 秒。
spark.executor.instances/
spark.executor.cores/
spark.executor.memory
spark/conf/spark-defaults.conf
查询
executors 和 CPU 核的个数,CarbonData 查询使用内存的大小。
在银行场景里,我们为每个执行器提供 4 个核以及 15GB 内存得到了很不错的性能,这两个参数并不是越多越好,在资源有限的情况下需要正确配置。比如银行场景里,每个节点有 32 个核,但是只有 64GB 的内存,所以我们不能提供很多的核,但是只给很少的内存。比如每个执行器配置 4 核以及 12GB 内存。在查询过程中,有时会发生 GC,这会对查询性能产生 3 到 15秒以上的影响。这个场景下需要增加内存或者是减少核的个数。
carbon.detail.batch.size
spark/carbonlib/carbon.properties
数据加载
用于存储从块扫描返回的记录缓冲区大小。
在使用 limit 场景下这个参数非常重要。比如你的查询限制为 1000,但是,如果我们将此值设置为 3000,这意味着我们从扫描中获得 3000 条记录,但 spark 只会获取 1000 行。所以剩下的 2000 是没用用到。在一次金融测试用例里,当我们将其设置为 100 之后,在查询限制为 1000 的情况下,相对于将这个值设置为 12000 能够得到 2 倍以上的性能提升。
carbon.use.local.dir
spark/carbonlib/carbon.properties
数据加载
是否使用 YARN 本地目录进行多表加载磁盘负载均衡
如果这个值设置为 true,CarbonData 将使用 YARN 本地目录进行多表加载磁盘负载均衡,这将提升数据加载的性能。
carbon.use.multiple.temp.dir
spark/carbonlib/carbon.properties
数据加载
在表数据加载期间是否使用多个 YARN 本地目录来实现磁盘负载均衡。
在启用 carbon.use.local.dir 之后,如果这个参数也设置为 true,CarbonData 将会在表数据加载期间是否使用所有 YARN 本地目录来实现磁盘负载均衡,这将提升数据加载的性能。在数据加载期间遇到磁盘热点问题时,请启用此属性。
carbon.sort.temp.compressor
spark/carbonlib/carbon.properties
数据加载
在数据加载的排序过程中指定压缩器来压缩中间排序的临时文件。
可选的值为 'SNAPPY','GZIP','BZIP2','LZ4' 以及空。默认情况下,Carbondata 不会压缩排序生成的临时文件。如果遇到磁盘瓶颈时,设置此参数将非常有用。
carbon.load.skewedDataOptimization.enabled
spark/carbonlib/carbon.properties
数据加载
是否启用基于大小的块分配策略来加载数据。
当加载数据时,carbondata 将使用基于文件大小的块分配策略进行任务分配。它将确保所有执行器处理相同大小的数据 -- 如果你的输入数据文件的大小差别很大(比如 1MB ~ 1GB)时很有用。
注意: 如果你的 CarbonData 实例仅用于查询,你可以在 spark 配置文件设置 spark.speculation = true 属性。