【问题标题】:Efficient way of finding elements that exists in one document but not the other in XQuery在 XQuery 中查找存在于一个文档中但不存在于另一个文档中的元素的有效方法
【发布时间】:2015-12-03 00:54:23
【问题描述】:

我有以下数据:

<Subjects>
    <Subject>
        <Id>1</Id>
        <Name>Maths</Name>
    </Subject>
    <Subject>
        <Id>2</Id>
        <Name>Science</Name>
    </Subject>
    <Subject>
        <Id>2</Id>
        <Name>Advanced Science</Name>
    </Subject>
    <Subject>
        <Id>500</Id>
        <Name>XYZ</Name>
    </Subject>
    <Subject>
        <Id>1000</Id>
        <Name>ABC</Name>
    </Subject>
</Subjects>

和:

<Courses>
    <Course>
        <SubjectId>1</SubjectId>
        <Name>Algebra I</Name>
    </Course>
    <Course>
        <SubjectId>1</SubjectId>
        <Name>Algebra II</Name>
    </Course>
    <Course>
        <SubjectId>1</SubjectId>
        <Name>Percentages</Name>
    </Course>
    <Course>
        <SubjectId>2</SubjectId>
        <Name>Physics</Name>
    </Course>
    <Course>
        <SubjectId>2</SubjectId>
        <Name>Biology</Name>
    </Course>
</Courses>

我希望能够使用5001000 获取subject 元素,因为它们不会出现在第二个XML 文档中。

我如何以最有效的方式做到这一点(请记住,我有大约 750 个科目,每个科目有 120 门课程)?

【问题讨论】:

  • 能否请您发布您目前采取/尝试这样做的方法?

标签: xml xpath xquery saxon xquery-3.0


【解决方案1】:

效率取决于您的优化器,但由于您在标签中提到了 Saxon,我想这就是我们可以定位的目标。假设您已将变量 $subjects$courses 分别绑定到 &lt;Subjects&gt;&lt;Courses&gt; 元素,最简单的查询可能是

$subjects/Subject[not(Id = $courses/Course/SubjectId)]

作为第一步,我会尝试运行它并查看它是否在可接受的时间内产生正确的结果;从那时起,它的性能调整工作。对于性能调整,请确保您拥有不同大小的源文档,以便您可以衡量性能如何随文档大小扩展。

通常,对于连接查询,Saxon-EE 在优化方面会比 Saxon-HE 做得更好,但我怀疑它在这方面会取得多大成功,因为谓词表示为否定。所以这可能会有二次性能。

为了手动优化这个,我会建立一个索引。在 XSLT 中可以使用 xsl:key 完成,在 XQuery 3.1 中可以使用映射完成。定义一个包含所有出现在 $courses 中的 SubjectId 的映射:

let $courseSubjects := map:merge($courses/Course/SubjectId ! map{.: true()})

然后使用它来选择:

return $subjects/Subject[not(map:contains($courseSubjects, Id))]

后记

我低估了 Saxon-EE 优化器。事实上,它确实生成了一个索引来支持对这个连接的评估。所以创建自己的地图可能是完全没有必要的。但我没有做过任何测量。

【讨论】:

  • 第一个将我的整个脚本的性能从 30,000 毫秒提高到 7,000 毫秒。第二个将其进一步减少到大约 4,000 毫秒!两者都产生正确的输出!谢谢!
猜你喜欢
  • 2018-12-14
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
相关资源
最近更新 更多