代码之家  ›  专栏  ›  技术社区  ›  Mike

BaseX:插入节点性能问题

  •  0
  • Mike  · 技术社区  · 7 年前

    我遇到了一些性能问题 insert 将XML节点映射到BASEX数据库中的现有节点。

    用例

    我有一个大的XML文件(大约2GB),我从中创建了一个BaseX数据库。XML看起来是这样(简化的)。大约有35万 <record> 学生:

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

    这个 <记录> s是相互关联的。这个 <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
    

    问题

    问题是我在将新节点插入到 <记录> . 在一个较小的测试数据库中,大约有10000个 <record>s ,插入的执行速度相当快-大约7秒。当我在我的生产数据库中运行相同的代码时 <录制>s ,一次插入操作需要几秒钟,甚至几分钟!而且会有上千个这样的插件,所以肯定需要很长时间。

    问题

    我对BaseX很陌生,我肯定不是最有经验的Java程序员。也许我只是忽略了一些事情或者犯了一些愚蠢的错误。所以我在问有没有人给我暗示。有什么问题吗?是Java代码吗?或者BaseX数据库有350.000个 <录制>s 对插入操作来说太大了?如果是:有解决办法吗?或者BaseX(或者通常是XML数据库)不是这个用例的合适工具?

    进一步信息

    我在Ubuntu 18.04上使用BaseX 9.0.2作为独立模式。在运行上述代码之前,我已经完成了“全部优化”。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Mike    6 年前

    我想我没有 optimize 正确地。在我之后 optimized 再一次 insert 命令执行得很快。现在,大约10000个插入在一秒钟内执行。也许这也有助于我停用 UPDINDEX AUTOOPTIMIZE .