BaseX:插入节点性能问题
BaseX: Inserting nodes performance problems
我在 insert
将 XML 节点连接到 BaseX 数据库中的现有节点时遇到一些性能问题。
用例
我有一个很大的 XML 文件(大约 2GB),我从中创建了一个 BaseX 数据库。 XML 看起来像这样(简化)。它有大约 350.000 <record>
s:
<collection>
<record>
<id>ABC007</id>
<title>The title of the record</title>
<author>Joe Lastname</author>
... [other information]
</record>
<record>
<id>ABC555</id>
<relation_id>ABC007</relation_id>
<title>Another title</title>
<author>Sue Lastname</author>
... [other information]
</record>
... [many other <record>s]
</collection>
<record>
是相互关联的。一条记录中的 <relation_id>
指向另一条记录中的 <id>
(参见上面的示例)。
我在 BaseX 中所做的是将信息从一条相关记录插入另一条记录,反之亦然。因此,结果如下所示:
<collection>
<record>
<id>ABC007</id>
<title>The title of the record</title>
<author>Joe Lastname</author>
... [other information]
<related_record> <!-- Insert this information -->
<title>Another title</title>
<author>Sue Lastname</author>
</related_record>
</record>
<record>
<id>ABC555</id>
<relation_id>ABC007</relation_id>
<title>Another title</title>
<author>Sue Lastname</author>
... [other information]
<related_record> <!-- Insert this information -->
<title>The title of the record</title>
<author>Joe Lastname</author>
</related_record>
</record>
... [many other <record>s that should be enriched with other records data]
</collection>
我正在使用以下 Java 代码:
// Setting some options and variables
Context context = new Context();
new Set(MainOptions.AUTOFLUSH, false).execute(context);
new Set(MainOptions.AUTOOPTIMIZE, false).execute(context);
new Set(MainOptions.UPDINDEX, true).execute(context);
// Opening the database
new Open('database_name').execute(context);
// Get all records with <relation_id> tags. These are the "child" records and they contain the "parent" record ID.
String queryParentIdsInChild = "for $childRecord in doc('xmlfile.xml')//record[relation_id]
return db:node-id($childRecord)"
// Iterate over the child records and get the parent record ID
QueryProcessor parentIdsInChildProc = new QueryProcessor(queryParentIdsInChild, context);
Iter iter = parentIdsInChildProc.iter();
parentIdsInChildProc.close();
for(Item childRecord; (childRecord = iter.next()) != null;) {
// Create a pointer to the child record in BaseX for convenience
String childNodeId = childRecord.toString();
String childNode = "db:open-id('database_name', " + childNodeId + ")";
// Get some details from the child record. They should be added to the parent record.
String queryChildDetails = "let $title := data("+childNode+"/title)"
+ " let $author := data("+childNode+"/author)"
+ " return "
+ "<related_record>"
+ " <title>{$title}</title>"
+ " <author>{$author}</author>"
+ "</related_record>";
String childDetails = new XQuery(queryChildDetails).execute(context);
// Create a pointer to the parent record in BaseX for convenience
parentNode = (... similar procedure like getting the child node, therefore skiping that code here)
// PERFORMANCE ISSUE HERE!!!
// Insert the child record details to the parent node
String parentUpdate = "insert node " + childDetails + " into " + parentNode;
new XQuery(parentUpdate).execute(context);
}
... flushing and optimizing code here
问题
问题是我在将新节点插入 <record>
时遇到了巨大的性能问题。在一个大约有 10.000 <record>s
的较小测试数据库中,插入的执行速度非常快 - 大约 7 秒。当我 运行 在我的生产数据库中使用大约 350.000 <record>s
相同的代码时,单个插入操作需要几秒钟,甚至几分钟!并且会有数千个这样的插入,所以肯定需要很长时间。
问题
我是 BaseX 的新手,我肯定不是最有经验的 Java 程序员。也许我只是忽略了某些东西或犯了一些愚蠢的错误。所以我问是否有人对我有提示。可能是什么问题呢?是 Java 代码吗?或者具有 350.000 <record>s
的 BaseX 数据库对于插入操作来说太大了吗?如果是:是否有解决方法?或者 BaseX(或一般的 XML 数据库)不是这个用例的正确工具?
更多信息
我在 Ubuntu 18.04 上以单机模式使用 BaseX 9.0.2。我在 运行 上面提到的代码之前做了一个 "Optimize All"。
我想我 运行 optimize
不正确。在我再次 optimized
之后 insert
命令 运行 非常快。现在,大约 10000 个插入在一秒钟内执行。也许它也有助于我停用 UPDINDEX
和 AUTOOPTIMIZE
.
我在 insert
将 XML 节点连接到 BaseX 数据库中的现有节点时遇到一些性能问题。
用例
我有一个很大的 XML 文件(大约 2GB),我从中创建了一个 BaseX 数据库。 XML 看起来像这样(简化)。它有大约 350.000 <record>
s:
<collection>
<record>
<id>ABC007</id>
<title>The title of the record</title>
<author>Joe Lastname</author>
... [other information]
</record>
<record>
<id>ABC555</id>
<relation_id>ABC007</relation_id>
<title>Another title</title>
<author>Sue Lastname</author>
... [other information]
</record>
... [many other <record>s]
</collection>
<record>
是相互关联的。一条记录中的 <relation_id>
指向另一条记录中的 <id>
(参见上面的示例)。
我在 BaseX 中所做的是将信息从一条相关记录插入另一条记录,反之亦然。因此,结果如下所示:
<collection>
<record>
<id>ABC007</id>
<title>The title of the record</title>
<author>Joe Lastname</author>
... [other information]
<related_record> <!-- Insert this information -->
<title>Another title</title>
<author>Sue Lastname</author>
</related_record>
</record>
<record>
<id>ABC555</id>
<relation_id>ABC007</relation_id>
<title>Another title</title>
<author>Sue Lastname</author>
... [other information]
<related_record> <!-- Insert this information -->
<title>The title of the record</title>
<author>Joe Lastname</author>
</related_record>
</record>
... [many other <record>s that should be enriched with other records data]
</collection>
我正在使用以下 Java 代码:
// Setting some options and variables
Context context = new Context();
new Set(MainOptions.AUTOFLUSH, false).execute(context);
new Set(MainOptions.AUTOOPTIMIZE, false).execute(context);
new Set(MainOptions.UPDINDEX, true).execute(context);
// Opening the database
new Open('database_name').execute(context);
// Get all records with <relation_id> tags. These are the "child" records and they contain the "parent" record ID.
String queryParentIdsInChild = "for $childRecord in doc('xmlfile.xml')//record[relation_id]
return db:node-id($childRecord)"
// Iterate over the child records and get the parent record ID
QueryProcessor parentIdsInChildProc = new QueryProcessor(queryParentIdsInChild, context);
Iter iter = parentIdsInChildProc.iter();
parentIdsInChildProc.close();
for(Item childRecord; (childRecord = iter.next()) != null;) {
// Create a pointer to the child record in BaseX for convenience
String childNodeId = childRecord.toString();
String childNode = "db:open-id('database_name', " + childNodeId + ")";
// Get some details from the child record. They should be added to the parent record.
String queryChildDetails = "let $title := data("+childNode+"/title)"
+ " let $author := data("+childNode+"/author)"
+ " return "
+ "<related_record>"
+ " <title>{$title}</title>"
+ " <author>{$author}</author>"
+ "</related_record>";
String childDetails = new XQuery(queryChildDetails).execute(context);
// Create a pointer to the parent record in BaseX for convenience
parentNode = (... similar procedure like getting the child node, therefore skiping that code here)
// PERFORMANCE ISSUE HERE!!!
// Insert the child record details to the parent node
String parentUpdate = "insert node " + childDetails + " into " + parentNode;
new XQuery(parentUpdate).execute(context);
}
... flushing and optimizing code here
问题
问题是我在将新节点插入 <record>
时遇到了巨大的性能问题。在一个大约有 10.000 <record>s
的较小测试数据库中,插入的执行速度非常快 - 大约 7 秒。当我 运行 在我的生产数据库中使用大约 350.000 <record>s
相同的代码时,单个插入操作需要几秒钟,甚至几分钟!并且会有数千个这样的插入,所以肯定需要很长时间。
问题
我是 BaseX 的新手,我肯定不是最有经验的 Java 程序员。也许我只是忽略了某些东西或犯了一些愚蠢的错误。所以我问是否有人对我有提示。可能是什么问题呢?是 Java 代码吗?或者具有 350.000 <record>s
的 BaseX 数据库对于插入操作来说太大了吗?如果是:是否有解决方法?或者 BaseX(或一般的 XML 数据库)不是这个用例的正确工具?
更多信息
我在 Ubuntu 18.04 上以单机模式使用 BaseX 9.0.2。我在 运行 上面提到的代码之前做了一个 "Optimize All"。
我想我 运行 optimize
不正确。在我再次 optimized
之后 insert
命令 运行 非常快。现在,大约 10000 个插入在一秒钟内执行。也许它也有助于我停用 UPDINDEX
和 AUTOOPTIMIZE
.