Oracle11g XQuery-为大型数据库优化查询

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/

我有一个很大的xml数据库(30000个文件,1.3版)。此数据库中的一个文件列出了数据库中存在的所有其他文件。我的目标是“简单地”检查数据库中是否存在列出的所有文件。但我必须注意的不是文件名,而是文档中的XML代码

这是这样的:

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 5,还可以使用查询控制台测试您的查询:

(http://hostname:8000/qconsole)

如果您有任何问题,请随时提问/让我知道进展如何。
我来自MarkLogic,很乐意提供帮助。

如果在比较中使用的每个属性上定义属性范围索引,MarkLogic应该可以快速处理查询

您可以通过MarkLogic管理UI执行此操作(http://hostname:8001):

  • 在“数据库”下选择您的数据库
  • 在中选择属性范围