簡體   English   中英

在XQuery中查找存在於一個文檔中而不是另一個文檔中的元素的有效方法

[英]Efficient way of finding elements that exists in one document but not the other in XQuery

我有以下數據:

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

我希望能夠獲得5001000subject元素,因為它們不會出現在第二個XML文檔中。

我如何以最有效的方式做到這一點(記得我有大約750個科目,每個科目有120門課程)?

效率取決於你的優化器,但是既然你在標簽中提到Saxon,我想這就是我們可以瞄准的目標。 最簡單的查詢,假設您已將變量$subjects$courses分別綁定到<Subjects><Courses>元素,可能是

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

作為第一步,我會嘗試運行它,看看它是否在可接受的時間內產生了正確的結果; 從那以后它的性能調整工作。 對於性能調整,請確保您具有不同大小的源文檔,以便您可以衡量性能如何隨文檔大小而變化。

通常對於連接查詢,Saxon-EE將比Saxon-HE做得更好,但是我懷疑它會在這個上面取得很大的成功,因為謂詞被表示為否定。 所以這可能會有二次性能。

為了手動優化這個,我會構建一個索引。 在XSLT中可以使用xsl:key完成,在XQuery 3.1中可以使用map完成。 定義一個包含$ courses中出現的所有SubjectId的地圖:

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

然后使用它來選擇:

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

后記

我低估了Saxon-EE優化器。 事實上,它確實生成了一個索引來支持對此連接的評估。 因此,創建自己的地圖可能是非常不必要的。 但我還沒有做過任何測量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM