我是exist数据库的初学者。我正在通过Java构建一个xml文档。我通过JAXB处理数据,然后通过插入更新插入到现有的数据库资源中。我现在用大约500个节点进行测试,在执行了几十个之后,每次插入需要10秒。我的XML具有以下通用结构。
<realestatedata>
<agents>
<author id="1">
<name>Author_A</name>
</author>
<author id="2">
<name>Author_B</name>
</author>
<portal id="1">
<name>Portal_A</name>
</portal>
</agents>
<artifacts>
<document id="1">
<latitude>51.37392</latitude>
<longitude>-0.00866</longitude>
<bathroom_number>1</bathroom_number>
<bedroom_number>3</bedroom_number>
<price>365000</price>
</document>
<theme id="1">
<name>Garden</name>
</theme>
<place id="1">
<name>BR4</name>
<location>
<lat>51.37392</lat>
<lon>-0.00866</lon>
</location>
</place>
</artifacts>
</realestatedata>
为了确保元素按正确的顺序放置,我使用以下代码进行插入更新,因此其类型的新记录要么是第一个,要么基于id附加在类似元素的末尾。
public void saveAuthor(Author author) {
XQueryService xQueryService = null;
CompiledExpression compiled = null;
int currentId = authorIdSequence.get();
StringWriter authorXml = new StringWriter();
try {
xQueryService = Utils.getXQeuryService();
if (getAuthorByName(author.getName()) == null) {
author.setId(String.valueOf(authorIdSequence.incrementAndGet()));
marshaller.marshal(author, authorXml);
if(currentId == 0){
compiled = xQueryService
.compile("update insert " + authorXml.toString()
+ " into //agents");
}
else{
compiled = xQueryService
.compile("update insert " + authorXml.toString()
+ " following //author[@id = '"+String.valueOf(currentId)+"']");
}
xQueryService.execute(compiled);
}
} catch (XMLDBException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
}
对文档、位置等其他元素执行相同的方法。经过几次更新后,速度变得非常慢。插入一条记录开始需要长达10秒的时间。
只有我能找到的相关链接是未被删除的。
http://sourceforge.net/mailarchive/forum.php?thread_name=s2s508bb1471004190430h8b42ee99o3f1835a9bc873d58%40mail.gmail.com&forum_name=存在开发
http://exist.2174344.n4.nabble.com/Slow-xquery-quot-update-insert-quot-performance-tt4657541.html#none
几个想法:
- 在大型节点集上运行属性过滤器(
[@id=…]
)时,速度可能非常慢。考虑一下,您发布的代码将要求eXist在找到插入新作者的正确位置之前,检查之前插入的每个作者的@id
。我可以想出几种方法来解决这个问题:@id
的范围索引会大大加快速度- 使用
@xml:id
而不是@id
可以让您使用id(…)
,这将更快。这需要将您的id更改为唯一的(例如"author_1"one_answers"portal_1") - 如果您真的总是递增
@id
值,那么新节点将始终具有最大的@id
。在这种情况下,following //author[last()]
甚至into //agents
都可以正常工作
- 执行许多小插入总是比执行一个大插入慢。如果可能的话,推迟将新数据保存到eXist,直到您一次有很多事情要做
- 确保您正在创建的
XQueryService
在完成它们之后得到了正确的发布。Utils.getXQueryService()
是否可能保留它不应该保留的引用 - 确保你没有不必要地增加开销。你能在通话之间重复使用
XQueryService
吗?如果getAuthorByName()
正在查询eXist,它是否可以与更新查询组合?您能否提供通过变量绑定插入的节点,而不是作为查询中的文字,以便每次都可以重用同一个编译后的查询
尽管如此,如果你只有500个节点,那么10秒对于一个插入来说是非常长的时间。在我的机器上使用未索引的"following"语法在一个查询中运行一批更新进行快速测试,可以在一半的时间内完成整个500次更新。很可能有更大的问题,在你的问题中并不明显。