我有超过1000万种形式的JSON文档:
["key": "val2", "key1" : "val", "{\"key\":\"val", \"key2\":\"val2"}"]
在一个文件中。
使用JAVA Driver API导入大约需要3个小时,同时使用以下功能(一次导入一个BSON):
public static void importJSONFileToDBUsingJavaDriver(String pathToFile, DB db, String collectionName) {
// open file
FileInputStream fstream = null;
try {
fstream = new FileInputStream(pathToFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("file not exist, exiting");
return;
}
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
// read it line by line
String strLine;
DBCollection newColl = db.getCollection(collectionName);
try {
while ((strLine = br.readLine()) != null) {
// convert line by line to BSON
DBObject bson = (DBObject) JSON.parse(JSONstr);
// insert BSONs to database
try {
newColl.insert(bson);
}
catch (MongoException e) {
// duplicate key
e.printStackTrace();
}
}
br.close();
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
有更快的方法吗?也许,MongoDB设置可能会影响插入速度? (例如,添加键:“_ id”将作为索引,因此MongoDB不必创建人工密钥,因此不必为每个文档编制索引)或在插入时完全禁用索引创建。 感谢。
答案 0 :(得分:8)
对不起,你们都在挑选性能问题,而不是核心问题。将逻辑与读取文件和插入分开是一个很小的收获。以二进制模式加载文件(通过MMAP)是一个很小的收获。使用mongo的批量插入是一个很大的收获,但仍然没有骰子。
整个性能瓶颈是BSON bson = JSON.parse(line)。或者换句话说,Java驱动程序的问题是它们需要从json转换为bson,而且这段代码似乎非常缓慢或者执行得很糟糕。通过JSON-simple或特别是通过JSON-smart完整的JSON(编码+解码)比JSON.parse()命令快100倍。
我知道Stack Overflow正在告诉我,我应该回答这个答案,我不是,但请放心,我仍然在寻找这个问题的答案。我无法相信所有关于Mongo性能的讨论,然后这个简单的示例代码失败如此悲惨。
答案 1 :(得分:5)
我已经完成了一个包含约250M记录的多行json文件。我只是使用mongoimport< data.txt,花了10个小时。与你的10M和3小时相比,我认为这要快得多。
另外根据我的经验,编写自己的多线程解析器会大大加快速度。程序很简单:
提醒:
如果需要性能,请不要使用流阅读器或任何内置的基于行的读取方法。他们很慢。只需使用二进制缓冲区并搜索'\ n'来标识一行,并且(最优选地)在缓冲区中进行就地解析而不创建字符串。否则垃圾收集者会对此不满意。
答案 2 :(得分:4)
您可以一次解析整个文件并在mongo文档中插入整个json,避免多个循环,您需要按如下方式分离逻辑:
1)解析文件并检索json对象。
2)解析结束后,将json对象保存在Mongo文档中。
答案 3 :(得分:3)
我有一个稍快的方式(我现在也插入了数百万),插入集合而不是单个文档
insert(List<DBObject> list)
http://api.mongodb.org/java/current/com/mongodb/DBCollection.html#insert(java.util.List)
那就是说,它并没有那么快。我即将尝试设置其他WriteConcerns而不是ACKNOWLEDGED(主要是UNACKNOWLEDGED),看看我是否可以加快速度。有关信息,请参阅http://docs.mongodb.org/manual/core/write-concern/
提高性能的另一种方法是在批量插入后创建索引。但是,除了一次性工作外,这很少是一种选择。
道歉,如果这听起来有点毛茸茸,我还在自己测试一下。好问题。
答案 4 :(得分:2)
使用批量操作insert / upserts。在Mongo 2.6
之后,您可以批量Updates/Upserts。下面的示例使用c#
驱动程序进行批量更新。
MongoCollection<foo> collection = database.GetCollection<foo>(collectionName);
var bulk = collection.InitializeUnorderedBulkOperation();
foreach (FooDoc fooDoc in fooDocsList)
{
var update = new UpdateDocument { {fooDoc.ToBsonDocument() } };
bulk.Find(Query.EQ("_id", fooDoc.Id)).Upsert().UpdateOne(update);
}
BulkWriteResult bwr = bulk.Execute();
答案 5 :(得分:1)
您也可以删除所有索引(当然除了PK索引)并在导入后重建它们。
答案 6 :(得分:0)
您可以使用批量插入
您可以在mongo website阅读文档,也可以在StackOverflow上查看java example