【问题标题】:BaseX: Inserting nodes performance problemsBaseX:插入节点性能问题
【发布时间】:2018-07-30 13:34:38
【问题描述】:

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

&lt;record&gt;s 彼此相关。一条记录中的&lt;relation_id&gt; 指向另一条记录中的&lt;id&gt;(参见上面的示例)。

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

问题

问题是我在将新节点插入&lt;record&gt; 时遇到了巨大的性能问题。在具有大约 10.000 &lt;record&gt;s 的较小测试数据库中,插入执行得非常快 - 大约 7 秒。当我在生产数据库中使用大约 350.000 &lt;record&gt;s 运行相同的代码时,单个插入操作需要几秒钟,甚至几分钟!而且会有数千个这样的插入,所以肯定需要很长时间。

问题

我对 BaseX 很陌生,而且我肯定不是最有经验的 Java 程序员。也许我只是忽略了某些东西或犯了一些愚蠢的错误。所以我问是否有人对我有提示。可能是什么问题呢?是Java代码吗?或者是具有 350.000 &lt;record&gt;s 的 BaseX 数据库对于插入操作来说太大了?如果是:有解决方法吗?还是 BaseX(或一般的 XML 数据库)不适合这个用例?

更多信息

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

【问题讨论】:

  • 您通常可以通过在 XQuery 中编写完整的插入过程来节省大量时间。你试过了吗?
  • 我将插入链接为逗号分隔的命令,例如 insert node &lt;test&gt;abc&lt;/test&gt; into db:open-id('db_name', 1), insert node &lt;test&gt;def&lt;/test&gt; into db:open-id('db_name', 2),... 。你是这么想的吗?事实上,这真的要快得多!
  • 您可以用一个 XQuery 表达式替换 80% 的 Java 代码。然后可以比单个 Java 命令调用更好地优化生成的查询。 – 也许 basex-talk 邮件列表会是一个更好的地方来进一步讨论这个……
  • 感谢您的提示,我发现,使用适当的 FLWOR 表达式,我需要做的几乎所有事情都可以在一个 XQuery 中完成。经过更多测试后,我将在这里发布我的解决方案。如果我还有其他问题,我会写信给您提到的邮件列表。

标签: java xml performance basex


【解决方案1】:

我认为我没有正确运行optimize。在我再次optimized 之后,insert 命令运行得非常快。现在,大约 10000 次插入在一秒钟内执行。也许我停用 UPDINDEX 和 AUTOOPTIMIZE 也有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 2017-01-02
    • 2011-05-20
    相关资源
    最近更新 更多