我有一个非常大的MySQL表(数十亿行,有几十列)我想在Cassandra中转换为ColumnFamily。我正在使用Hector。
我首先创建我的架构:
String clusterName = "Test Cluster";
String host = "cassandra.lanhost.com:9160";
String newKeyspaceName = "KeyspaceName";
String newColumnFamilyName = "CFName";
ThriftCluster cassandraCluster;
CassandraHostConfigurator cassandraHostConfigurator;
cassandraHostConfigurator = new CassandraHostConfigurator(host);
cassandraCluster = new ThriftCluster(clusterName, cassandraHostConfigurator);
BasicColumnFamilyDefinition columnFamilyDefinition = new BasicColumnFamilyDefinition();
columnFamilyDefinition.setKeyspaceName(newKeyspaceName);
columnFamilyDefinition.setName(newColumnFamilyName);
columnFamilyDefinition.setDefaultValidationClass("UTF8Type");
columnFamilyDefinition.setKeyValidationClass(ComparatorType.UTF8TYPE.getClassName());
columnFamilyDefinition.setComparatorType(ComparatorType.UTF8TYPE);
BasicColumnDefinition columnDefinition = new BasicColumnDefinition();
columnDefinition.setName(StringSerializer.get().toByteBuffer("id"));
columnDefinition.setIndexType(ColumnIndexType.KEYS);
columnDefinition.setValidationClass(ComparatorType.INTEGERTYPE.getClassName());
columnDefinition.setIndexName("id_index");
columnFamilyDefinition.addColumnDefinition(columnDefinition);
columnDefinition = new BasicColumnDefinition();
columnDefinition.setName(StringSerializer.get().toByteBuffer("status"));
columnDefinition.setIndexType(ColumnIndexType.KEYS);
columnDefinition.setValidationClass(ComparatorType.ASCIITYPE.getClassName());
columnDefinition.setIndexName("status_index");
columnFamilyDefinition.addColumnDefinition(columnDefinition);
.......
ColumnFamilyDefinition cfDef = new ThriftCfDef(columnFamilyDefinition);
KeyspaceDefinition keyspaceDefinition =
HFactory.createKeyspaceDefinition(newKeyspaceName, "org.apache.cassandra.locator.SimpleStrategy", 1, Arrays.asList(cfDef));
cassandraCluster.addKeyspace(keyspaceDefinition);
完成后,我加载存储在List中的数据,因为我使用namedParametersJdbcTemplate获取MySQL数据,如下所示:
String clusterName = "Test Cluster";
String host = "cassandra.lanhost.com:9160";
String KeyspaceName = "KeyspaceName";
String ColumnFamilyName = "CFName";
final StringSerializer serializer = StringSerializer.get();
public void insert(List<SqlParameterSource> dataToInsert) throws ExceptionParserInterrupted {
Keyspace workingKeyspace = null;
Cluster cassandraCluster = HFactory.getOrCreateCluster(clusterName, host);
workingKeyspace = HFactory.createKeyspace(KeyspaceName, cassandraCluster);
Mutator<String> mutator = HFactory.createMutator(workingKeyspace, serializer);
ColumnFamilyTemplate<String, String> template = new ThriftColumnFamilyTemplate<String, String>(workingKeyspace, ColumnFamilyName, serializer, serializer);
long t1 = System.currentTimeMillis();
for (SqlParameterSource data : dataToInsert) {
String keyId = "id" + (Integer) data.getValue("id");
mutator.addInsertion(keyId, ColumnFamilyName, HFactory.createColumn("id", (Integer) data.getValue("id"), StringSerializer.get(), IntegerSerializer.get()));
mutator.addInsertion(keyId,ColumnFamilyName, HFactory.createStringColumn("status", data.getValue("status").toString()));
...............
}
mutator.execute();
System.out.println(t1 - System.currentTimeMillis());
我在大约1小时内插入10万行,这真的很慢。我听说过多线程我的插页,但在这种特殊情况下,我不知道该怎么做。我应该使用BatchMutate吗?
答案 0 :(得分:1)
有另一种方法可以实现这一目标。您可以尝试浏览https://github.com/impetus-opensource/Kundera。你会喜欢的。
Kundera是一个符合JPA 2.0标准的NoSQL数据存储区对象数据存储映射库,目前支持Cassandra,HBase,MongoDB和所有关系数据存储区(Kundera内部对所有关系数据存储区使用Hibernate)。
在您的情况下,您可以使用现有对象和JPA注释将它们存储在Cassandra中。由于Kundera支持多语言持久性,因此您还可以使用MySQL + Cassandra组合,您可以将MySQL用于大多数数据,使用Cassandra进行事务数据。由于您需要关注的是对象和JPA注释,因此您的工作将更容易。
要获得表现,您可以查看https://github.com/impetus-opensource/Kundera/wiki/Kundera-Performance
答案 1 :(得分:1)
是的,您应该从多个线程运行插入代码。请查看以下压力测试代码,了解如何使用hector有效地执行此操作: https://github.com/zznate/cassandra-stress
插入性能问题的另一个来源可能是您在列族上应用的二级索引的数量(每个二级索引在引擎盖下创建一个额外的列族)。
正确设计的数据模型不应该真正需要大量的二级索引。以下文章提供了Cassandra中数据建模的一个很好的概述: http://www.datastax.com/docs/1.0/ddl/index