使用 xquery 和 FLWOR 在 BaseX 中迭代大型 XML 文档的最有效方法
Most efficient way to iterate through big XML documents in BaseX using xquery and FLWOR
我遇到了一个有趣的问题,我需要遍历多个大 XML 文件(每个文件有数百 MB)并从每个元素输出特定数据,并且尽可能快地完成可能的。
示例:
Points.xml:
<points>
<point>
<identifier>bb25c66c-27d0-447f-aaad-bd8290b332fd</identifier>
<name>A</name>
</point>
<point>
<identifier>f187cc74-2709-4464-995c-b3bdcae46b39</identifier>
<name>B</name>
</point>
</points>
Routes.xml:
<routes>
<route>
<pointLink xlink:href="urn:uuid:bb25c66c-27d0-447f-aaad-bd8290b332fd"/>
<name>1</name>
</route>
<route>
<pointLink xlink:href="urn:uuid:f187cc74-2709-4464-995c-b3bdcae46b39"/>
<name>2</name>
</route>
</routes>
在不同的文档中有数以万计的point/route元素,它们比这复杂得多,但是对于这个例子,这个摘录就足够了。
输出需要是这样的:
1 - A
2 - B
我无法修改文档本身,这是我必须处理的,现在的问题是 - 如何尽可能高效地 link 基于标识符的元素?我说的是做这件事的方法,也许是一种不同的思考方式,而不是实际的代码,因为无论如何最终都会有很大的不同。
我试过遍历路线,然后使用 FLWOR 找到点:
for $route in doc('routes.xml')/routes/route
return concat(
$route/name/text(),
' - ',
doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]/name/text()
)
结果不是很好(花了将近一个小时才完成)。这种方法也有类似的故事:
for $route in doc('routes.xml')/routes/route,
$point in doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]
return concat(
$route/name/text(),
' - ',
$point/name/text()
)
最后,我需要在输出中使用更多来自 point/route 的子元素,所以我想我必须用 for 迭代它们然后连接输出,但也许我错了,这这就是我在这里问的原因。
我是否忽略了什么,或者没有更快的方法来做到这一点?
正如 Martin Honnen 在评论中所说,确实存在索引问题。
简单地创建属性索引(CREATE INDEX 属性)有助于将查询时间从大约 45 分钟减少到不到一秒。不可思议。
我遇到了一个有趣的问题,我需要遍历多个大 XML 文件(每个文件有数百 MB)并从每个元素输出特定数据,并且尽可能快地完成可能的。 示例:
Points.xml:
<points>
<point>
<identifier>bb25c66c-27d0-447f-aaad-bd8290b332fd</identifier>
<name>A</name>
</point>
<point>
<identifier>f187cc74-2709-4464-995c-b3bdcae46b39</identifier>
<name>B</name>
</point>
</points>
Routes.xml:
<routes>
<route>
<pointLink xlink:href="urn:uuid:bb25c66c-27d0-447f-aaad-bd8290b332fd"/>
<name>1</name>
</route>
<route>
<pointLink xlink:href="urn:uuid:f187cc74-2709-4464-995c-b3bdcae46b39"/>
<name>2</name>
</route>
</routes>
在不同的文档中有数以万计的point/route元素,它们比这复杂得多,但是对于这个例子,这个摘录就足够了。
输出需要是这样的:
1 - A
2 - B
我无法修改文档本身,这是我必须处理的,现在的问题是 - 如何尽可能高效地 link 基于标识符的元素?我说的是做这件事的方法,也许是一种不同的思考方式,而不是实际的代码,因为无论如何最终都会有很大的不同。
我试过遍历路线,然后使用 FLWOR 找到点:
for $route in doc('routes.xml')/routes/route
return concat(
$route/name/text(),
' - ',
doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]/name/text()
)
结果不是很好(花了将近一个小时才完成)。这种方法也有类似的故事:
for $route in doc('routes.xml')/routes/route,
$point in doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]
return concat(
$route/name/text(),
' - ',
$point/name/text()
)
最后,我需要在输出中使用更多来自 point/route 的子元素,所以我想我必须用 for 迭代它们然后连接输出,但也许我错了,这这就是我在这里问的原因。
我是否忽略了什么,或者没有更快的方法来做到这一点?
正如 Martin Honnen 在评论中所说,确实存在索引问题。 简单地创建属性索引(CREATE INDEX 属性)有助于将查询时间从大约 45 分钟减少到不到一秒。不可思议。