0

我是exist-db的初学者。我正在通过 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();
    }
}

对文档、位置等其他元素执行相同的方法。经过几次更新后,它变得非常慢。插入一条记录开始最多需要十秒钟。

只有我能找到的相关链接没有回答。

http://sourceforge.net/mailarchive/forum.php?thread_name=s2s508bb1471004190430h8b42ee99o3f1835a9bc873d58%40mail.gmail.com&forum_name=exist-development

http://exist.2174344.n4.nabble.com/Slow-xquery-quot-update-insert-quot-performance-tt4657541.html#none

4

1 回答 1

2

一些想法:

  • [@id=…]在大量节点上运行时,属性过滤器 ( ) 可能会非常慢。考虑到您发布的代码将要求 eXist@id在找到插入新作者的正确位置之前检查每个先前插入的作者的作者。我可以想出几种方法来解决这个问题:
    1. 's上的范围索引@id会大大加快速度。
    2. 使用@xml:id而不是@id会让你使用id(…)哪个会更快。这需要将您的 id 更改为唯一的(例如“author_1”和“portal_1”)
    3. 如果您真的总是在增加您的@id值,那么新节点将始终具有最大的@id. 在那种情况下,following //author[last()]甚至into //agents会工作得很好。
  • 做许多小的插入总是比做一个大的插入要慢。如果可能,请延迟将新数据保存到 eXist,直到您同时有一堆事情要做。
  • 确保XQueryService您创建的 s 在完成后正确发布。是否Utils.getXQueryService()可能保留不应该的引用?
  • 确保您没有不必要地增加开销。XQueryService您可以在通话之间重用s 吗?如果getAuthorByName()是查询eXist,可以和更新查询结合使用吗?您能否提供节点以通过变量绑定插入而不是作为查询中的文字,以便您每次都可以重用相同的编译查询?

尽管如此,如果您只有 500 个节点,那么 10 秒对于单个插入来说是非常长的时间。在我的机器上使用未索引的“以下”语法在单个查询中运行一批更新的快速测试可以在一半的时间内完成整个 500 次更新。很可能有一些更大的问题在你的问题中并不明显。

于 2013-09-18T06:05:47.880 回答