我开始讨论,我希望,它将成为讨论使用mutators Vs的数据加载方法的一个地方。通过'LOAD DATA INFILE'使用平面文件加载。
我一直很困惑,使用mutator获得巨大的性能提升(使用批量大小= 1000或10000或100K等)。
我的项目涉及将近4亿行社交媒体数据加载到HyperTable中,以用于实时分析。我花了将近3天才加载了100万行数据(下面的代码示例)。每行大约32字节。因此,为了避免花费2-3周来加载这么多数据,我准备了一个包含行的平面文件并使用了DATA LOAD INFILE方法。性能提升令人惊叹。使用此方法,加载速率为368336个细胞/秒。
See below for actual snapshot of action:
hypertable> LOAD DATA INFILE "/data/tmp/users.dat" INTO TABLE users;
Loading 7,113,154,337 bytes of input data...
0% 10 20 30 40 50 60 70 80 90 100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Load complete.
Elapsed time: 508.07 s
Avg key size: 8.92 bytes
Total cells: 218976067
Throughput: 430998.80 cells/s
Resends: 2210404
hypertable> LOAD DATA INFILE "/data/tmp/graph.dat" INTO TABLE graph;
Loading 12,693,476,187 bytes of input data...
0% 10 20 30 40 50 60 70 80 90 100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Load complete.
Elapsed time: 1189.71 s
Avg key size: 17.48 bytes
Total cells: 437952134
Throughput: 368118.13 cells/s
Resends: 1483209
为什么2方法之间的性能差异如此之大?什么是增强mutator性能的最佳方法。示例mutator代码如下:
my $batch_size = 1000000; # or 1000 or 10000 make no substantial difference
my $ignore_unknown_cfs = 2;
my $ht = new Hypertable::ThriftClient($master, $port);
my $ns = $ht->namespace_open($namespace);
my $users_mutator = $ht->mutator_open($ns, 'users', $ignore_unknown_cfs, 10);
my $graph_mutator = $ht->mutator_open($ns, 'graph', $ignore_unknown_cfs, 10);
my $keys = new Hypertable::ThriftGen::Key({ row => $row, column_family => $cf, column_qualifier => $cq });
my $cell = new Hypertable::ThriftGen::Cell({key => $keys, value => $val});
$ht->mutator_set_cell($mutator, $cell);
$ht->mutator_flush($mutator);
我很感激对此的任何意见?我没有大量的HyperTable经验。
感谢。
答案 0 :(得分:2)
如果要花三天时间加载一百万行,那么你可能在每一行插入后调用flush(),这不是正确的做法。在我描述hot以解决这个问题之前,你的mutator_open()参数并不完全正确。你不需要指定ignore_unknown_cfs,你应该为flush_interval提供0,如下所示:
my $users_mutator = $ht->mutator_open($ns, 'users', 0, 0);
my $graph_mutator = $ht->mutator_open($ns, 'graph', 0, 0);
如果要检查已消耗了多少输入数据,则只应调用mutator_flush()。成功调用mutator_flush()意味着已经插入该mutator的所有数据都已经持久地进入数据库。如果你没有检查点消耗了多少输入数据,那么就不需要调用mutator_flush(),因为当你关闭mutator时它会自动刷新。
我看到你的代码的下一个性能问题是你正在使用mutator_set_cell()。你应该使用mutator_set_cells()或mutator_set_cells_as_arrays(),因为每次方法调用都是ThriftBroker的往返,这是很昂贵的。通过使用mutator_set_cells_ *方法,您可以在许多单元格上分摊该往返。对于与本机数据类型(例如字符串)相比,对象构造开销较大的语言,mutator_set_cells_as_arrays()方法可以更有效。我不确定Perl,但你可能想尝试一下,看看它是否能提升性能。
另外,当你完成mutator时,一定要调用mutator_close()。