2013-08-22 61 views
0

我是存在db的初学者。我正在通过Java构建一个XML文档。我通过JAXB处理数据,然后通过插入更新插入到exists-db资源。目前我正在测试大约500个节点,并且在几十个执行完成后,每插入一次最多需要10秒。我的XML具有以下一般结构。存在db更新插入很慢

<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> 

为了确保元件被放置在正确的顺序中,我使用的嵌件更新下面的代码,以便它的类型的一个新的记录是第一一个或基于IDS相似的元件的端部被附加。

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

回答

2

的一点想法:当对大量节点上运行

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

尽管如此,如果只有500个节点,单个插入10s是一个非常长的时间。在我的机器上使用未索引的“跟随”语法在单个查询中运行一批更新的快速测试可以在一半的时间内完成500次。很可能有更大的错误在你的问题中不明显。