Oracle11g XQuery-为大型数据库优化查询
我有一个很大的xml数据库(30000个文件,1.3版)。此数据库中的一个文件列出了数据库中存在的所有其他文件。我的目标是“简单地”检查数据库中是否存在列出的所有文件。但我必须注意的不是文件名,而是文档中的XML代码 这是这样的:Oracle11g XQuery-为大型数据库优化查询,oracle11g,query-optimization,xquery,marklogic,Oracle11g,Query Optimization,Xquery,Marklogic,我有一个很大的xml数据库(30000个文件,1.3版)。此数据库中的一个文件列出了数据库中存在的所有其他文件。我的目标是“简单地”检查数据库中是否存在列出的所有文件。但我必须注意的不是文件名,而是文档中的XML代码 这是这样的: declare variable $root := fn:collection(); declare function local:isValid($fileCode) { let $fileSearchedIdentCode := $root/dmodule/
declare variable $root := fn:collection();
declare function local:isValid($fileCode) {
let $fileSearchedIdentCode := $root/dmodule/identity/dmCode
return
$fileCode/@attribute1 = $fileSearchedIdentCode/@attribute1 and
$fileCode/@attribute2 = $fileSearchedIdentCode/@attribute2 and
$fileCode/@attribute3 = $fileSearchedIdentCode/@attribute3
};
<result>
{
for $fileCode in $root/file[identity/@fileType eq 'listOfFiles']/fileContent/fileEntry/fileCode
return
if (local:isValid($fileCode))
then <filePresent>1</filePresent>
else <fileNonPresent>2</fileNonPresent>
}
</result>
声明变量$root:=fn:collection();
声明函数本地:isValid($fileCode){
让$fileSearchedIdentCode:=$root/dmodule/identity/dmCode
返回
$fileCode/@attribute1=$fileSearchedIdentCode/@attribute1和
$fileCode/@attribute2=$fileSearchedIdentCode/@attribute2和
$fileCode/@attribute3=$fileSearchedIdentCode/@attribute3
};
{
对于$root/file[identity/@fileType eq'listOfFiles']/fileContent/fileEntry/fileCode中的$fileCode
返回
if(本地:isValid($fileCode))
那么1
其他2
}
上面的代码是为一个小型数据库运行的,但对我来说,它需要花费大量的时间
因此,我想知道是否有人可以帮助我改进代码,以便在合理的时间内执行;)
(我的数据库已编制索引)
谢谢你的帮助
Johann用等号(=)替换“eq”有帮助吗?用等号(=)替换“eq”有帮助吗?属性索引似乎没有应用于
local:isValid
函数中的属性检查。您可以通过将它们重写为XPath谓词来实现这一点:
declare variable $root := fn:collection();
declare function local:isValid($fileCode) {
$root/dmodule/identity/dmCode[@attribute1 = $fileCode/@attribute1
and @attribute2 = $fileCode/@attribute2
and @attribute3 = $fileCode/@attribute3]
};
<result> {
for $fileCode in $root/file[identity/@fileType = 'listOfFiles']/fileContent/fileEntry/fileCode
return
if (local:isValid($fileCode))
then <filePresent>1</filePresent>
else <fileNonPresent>2</fileNonPresent>
}</result>
对于我的测试数据,评估时间从4'500ms下降到~20ms。似乎属性索引没有应用于local:isValid
函数中的属性检查。您可以通过将它们重写为XPath谓词来实现:
declare variable $root := fn:collection();
declare function local:isValid($fileCode) {
$root/dmodule/identity/dmCode[@attribute1 = $fileCode/@attribute1
and @attribute2 = $fileCode/@attribute2
and @attribute3 = $fileCode/@attribute3]
};
<result> {
for $fileCode in $root/file[identity/@fileType = 'listOfFiles']/fileContent/fileEntry/fileCode
return
if (local:isValid($fileCode))
then <filePresent>1</filePresent>
else <fileNonPresent>2</fileNonPresent>
}</result>
对于我的测试数据,评估时间从4'500ms下降到~20ms。您的测试系统列表中没有包含eXist db,但如果您有兴趣使用数据对其进行基准测试,那么有一篇关于优化查询并智能地使用索引以加快eXist db性能的文章。请参阅。随您的便查询发布它应该可以正常工作,不需要修改,但文章中的建议肯定会帮助您提高性能。如果您需要帮助,请随时发布到现有的开放邮件列表 无论你采用哪种系统,我都非常有兴趣知道你的结果——不仅仅是我——我认为会有广泛的兴趣
祝您好运!您的测试系统列表中没有包含eXist db,但如果您有兴趣使用数据对其进行基准测试,那么下面有一篇关于优化查询并智能使用索引以提高eXist db性能的文章。请参阅。发布时的查询应该可以正常工作,无需修改,但是文章中的副作用肯定会帮助您提高性能。如果您需要帮助,请随时发布到exist open邮件列表 无论你采用哪种系统,我都非常有兴趣知道你的结果——不仅仅是我——我认为会有广泛的兴趣
祝您好运!对于MarkLogic,您需要知道索引查找只在某些表达式和函数中发生。在这种情况下,您需要更紧凑的代码。下面的表单应该产生相同的结果,但将以简单的方式使用索引:
<result>
{
for $fileCode in
collection()/
file[identity/@fileType eq "listOfFiles"]/
fileContent/
fileEntry/
fileCode
let $fc1 := $fileCode/@attribute1/string()
let $fc2 := $fileCode/@attribute2/string()
let $fc3 := $fileCode/@attribute3/string()
return
if (collection()/
dmodule/
identity/
dmCode[
@attribute1 eq $fc1][
@attribute2 eq $fc2][
@attribute3 eq $fc3])
then <filePresent>1</filePresent>
else <fileNonPresent>2</fileNonPresent>
}
</result>
这只需要一次数据库查找,并在内存中完成其余必要的工作。它的伸缩性应该比原始查询或我的第一次迭代要好得多。如果您不同意我对结果格式的修改,并且仍然希望看到每个输入的结果文件代码
,您可以重构…where…return…
子句到…返回…if…then…else…
与原始查询一样
请务必在中使用配置文件工具-它可以帮助您尝试替代方案并发现优化机会。对于MarkLogic,您需要知道索引查找仅在某些表达式和函数中发生。在这种情况下,您需要更紧凑的代码。下面的表单应该产生相同的结果,但将使用索引in简单地说:
<result>
{
for $fileCode in
collection()/
file[identity/@fileType eq "listOfFiles"]/
fileContent/
fileEntry/
fileCode
let $fc1 := $fileCode/@attribute1/string()
let $fc2 := $fileCode/@attribute2/string()
let $fc3 := $fileCode/@attribute3/string()
return
if (collection()/
dmodule/
identity/
dmCode[
@attribute1 eq $fc1][
@attribute2 eq $fc2][
@attribute3 eq $fc3])
then <filePresent>1</filePresent>
else <fileNonPresent>2</fileNonPresent>
}
</result>
这只需要一次数据库查找,并在内存中完成其余必要的工作。它的伸缩性应该比原始查询或我的第一次迭代要好得多。如果您不同意我对结果格式的修改,并且仍然希望看到每个输入的结果文件代码
,您可以重构…where…return…
子句到…返回…if…then…else…
与原始查询一样
请确保在中使用配置文件工具-它可以帮助您尝试备选方案并发现优化机会。如果您在比较中使用的每个属性上定义了属性范围索引,则MarkLogic应该可以快速处理查询 您可以通过MarkLogic管理UI执行此操作(http://hostname:8001):
- 在“数据库”下选择您的数据库
- 选择左侧的属性范围索引
- 选择“添加”以定义新的属性范围索引
- 指定引用范围索引的元素(dmcode)和属性(attribute1、attribute2、attribute3)(如果元素位于某个命名空间中,请不要忘记指定命名空间)
- 单击“确定”创建范围索引
我来自MarkLogic,很乐意提供帮助。如果在比较中使用的每个属性上定义属性范围索引,MarkLogic应该可以快速处理查询 您可以通过MarkLogic管理UI执行此操作(http://hostname:8001):
- 在“数据库”下选择您的数据库
- 在中选择属性范围