本教程将指导你如何创建 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 |
... | ... | 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')
对于测量类型(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 倍。
考虑每天加载数据的场景,每次加载 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 做了一些性能测试。它涉及详细的查询和聚合场景。影响性能的配置已经被确定,并归纳到以下表中 :
属性 | 位置 | 使用场景 | 模式 | 训练 |
---|---|---|---|---|
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 属性。