提高 SQL Server 中的 Xquery 性能

2024-01-28

我有一个 Azure SQL 数据库,其中有 1 个表和大量记录(超过 75,000 条)。该表包含 XML 数据类型的列。此列如下所示:

<error application="application" host="host" type="exception" message="message" ...>
  <serverVariables>
    <item name="name1">
      <value string="text" />
    </item>
    <item name="name2">
      <value string="text2" />
    </item>
    <item name="name3">
      <value string="text3" />
    </item>
    <item name="name4">
      <value string="text4" />
    </item>
    <item name="name5">
      <value string="text5" />
    </item>
    <item name="name6">
      <value string="text6" />
    </item>
    <item name="name7">
      <value string="text7" />
    </item>
  </serverVariables>
</error>

如果我想获取item属性名称为的所有记录name5值属性字符串是text5我会写一个这样的查询:

SELECT *
FROM Table
WHERE XmlColumn.exist('//item[@name[. = "name5"] and value/@string[. = "text5"]]') = 1

这使用 XQuery 并且必须查询整个文档。这也很慢。

我的问题是如何才能使这个查询执行得更快?是否可以在该列上声明 XML 索引?是否还有其他方法可以使 XQuery 执行得更快?


我刚刚做了一个小测试。和.nodes()你可以获得大约 3%...实际上不多。在我的测试机器(只是一台简单的笔记本电脑)中,我在大约 5 秒内得到了 100.000 行的结果。事实上,还不错...如果您想要快速,则必须从 XML 中获取搜索值,或者使用 XML 索引:

测试场景

首先,我创建一个测试表并填充 100.000 行。随机数(0 到 1000)应为每个随机数生成约 100 行。该数字被放入 varchar col 中and作为 XML 中的值。

然后我会像你需要的那样拨打电话.exist().nodes()第二个稍有优势,但都需要 5 至 6 秒。 事实上,我执行了两次调用:第二次以交换的顺序进行,并稍微更改了搜索参数,并使用“//item”而不是完整路径,以避免通过缓存的结果或计划出现误报。

然后我创建一个 XML 索引并执行相同的调用

怎么办really确实让我惊讶! - 这.nodes with 完整路径 is much比以前慢(9秒)但是.exist()缩短至半秒,完整路径甚至缩短至约 0.10 秒

所以我的建议:使用索引并用.exist()

这是复制粘贴和自测试的代码

CREATE TABLE #testTbl(ID INT IDENTITY PRIMARY KEY, SomeData VARCHAR(100),XmlColumn XML);
GO

DECLARE @RndNumber VARCHAR(100)=(SELECT CAST(CAST(RAND()*1000 AS INT) AS VARCHAR(100)));

INSERT INTO #testTbl VALUES('Data_' + @RndNumber,
'<error application="application" host="host" type="exception" message="message" >
  <serverVariables>
    <item name="name1">
      <value string="text" />
    </item>
    <item name="name2">
      <value string="text2" />
    </item>
    <item name="name3">
      <value string="text3" />
    </item>
    <item name="name4">
      <value string="text4" />
    </item>
    <item name="name5">
      <value string="My test ' +  @RndNumber + '" />
    </item>
    <item name="name6">
      <value string="text6" />
    </item>
    <item name="name7">
      <value string="text7" />
    </item>
  </serverVariables>
</error>');

GO 100000

DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesFullPath_no_index;
GO

DECLARE @d DATETIME=GETDATE();
SELECT * 
FROM #testTbl
--WHERE XmlColumn.exist('//item[@name[. = "name5"] and value/@string[. = "My test 600"]]') = 1
--The same, just a bit shorter...
WHERE XmlColumn.exist('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistFullPath_no_index;
GO

DECLARE @d DATETIME=GETDATE();
SELECT * 
FROM #testTbl
--WHERE XmlColumn.exist('//item[@name[. = "name5"] and value/@string[. = "My test 600"]]') = 1
--The same, just a bit shorter...
WHERE XmlColumn.exist('//item[@name="name5" and value/@string="My test 500"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistShortPath_no_index;
GO

DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('//item[@name="name5" and value/@string="My test 500"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesShortPath_no_index;
GO

CREATE PRIMARY XML INDEX PXML_test_XmlColum1 ON #testTbl(XmlColumn);
CREATE XML INDEX IXML_test_XmlColumn2 ON #testTbl(XmlColumn) USING XML INDEX PXML_test_XmlColum1 FOR PATH;
GO

DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesFullPath_with_index;
GO

DECLARE @d DATETIME=GETDATE();
SELECT * 
FROM #testTbl
--WHERE XmlColumn.exist('//item[@name[. = "name5"] and value/@string[. = "My test 600"]]') = 1
--The same, just a bit shorter...
WHERE XmlColumn.exist('/error/serverVariables/item[@name="name5" and value/@string="My test 600"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistFullPath_with_index;
GO

DECLARE @d DATETIME=GETDATE();
SELECT * 
FROM #testTbl
--WHERE XmlColumn.exist('//item[@name[. = "name5"] and value/@string[. = "My test 600"]]') = 1
--The same, just a bit shorter...
WHERE XmlColumn.exist('//item[@name="name5" and value/@string="My test 500"]') = 1;
SELECT CAST(GETDATE()-@d AS TIME) AS ExistShortPath_with_index;
GO
    
DECLARE @d DATETIME=GETDATE()
SELECT #testTbl.*
FROM #testTbl
CROSS APPLY XmlColumn.nodes('//item[@name="name5" and value/@string="My test 500"]') AS a(b);
SELECT CAST(GETDATE()-@d AS TIME) AS NodesShortPath_with_index;
GO

DROP TABLE #testTbl;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

提高 SQL Server 中的 Xquery 性能 的相关文章

随机推荐

  • 如何将移动构造函数与二维数组 (**) 一起使用?

    可能是我错误地编码了我的类 但是当我使用移动构造函数而不是复制 cotr 作为重载之一 而不是准确地说 时 我的程序崩溃了 例如 class Sample int a int b constructor declarations 在 cpp
  • python 按键简单游戏

    我想在屏幕上看到一个符号 例如可能是 散列 符号会有一些起始位置 比如说 0 0 如果我按向右箭头 我希望看到标志向右移动 如果按向左箭头 我希望看到标志向左移动 等等 到目前为止 我的代码看起来像这样 它适用于读取 pos 但我想添加某种
  • Delphi 如何获取控件上的光标位置?

    我想知道 TCustomControl 上光标的位置 如何找到坐标 获取光标位置 http msdn microsoft com en us library ms648390 28v vs 85 29 aspx如果您无法处理鼠标事件 这会很
  • 动画 UIButton 的标题更改

    在这里我找到了如何制作动画UIButton的标题更改使用现已弃用beginAnimations context method iPhone 的 UIBUtton 标题动画 https stackoverflow com questions
  • 在 ASP.NET WebApi 2 中实现移动应用程序的外部身份验证

    我正在尝试构建一个 API 使用 ASP NET WebApi 该 API 将由学校项目的本机移动应用程序使用 我不关心 开发移动应用程序 这个责任由不同的成员承担 我现在需要实现基于令牌的 Facebook 登录 有很多教程可用于介绍如何
  • 如何以编程方式获取 Admob 的设备 ID?

    我有多个设备 而且可能还会有更多 并且不想一一添加 有人知道 Admob 使用什么 ID 吗 String aid Settings Secure getString getContext getContentResolver androi
  • Gem 安装错误可写和 PATH

    这是我遇到的两个错误 我使用的是 OS X 老实说 不知道我是否通过 gem 安装 如果这很重要的话 WARNING Installing to gem since Library Ruby Gems 1 8 and usr bin are
  • 将列表拆分为单独但重叠的块

    假设我有一个清单A A 1 2 3 4 5 6 7 8 9 10 我想创建一个新列表 比如说B 按以下顺序使用上面的列表 B 1 2 3 3 4 5 5 6 7 7 8 9 9 10 即前 3 个数字为A 0 1 2 后 3 个数字为A 2
  • GAE 云数据存储:获取最常编写的模型

    我正在尝试按最常编写的模型的降序排列模型列表 这是我到目前为止所尝试过的 client查询集提供模型及其属性 属性的详细信息 以及这些模型相关的详细信息 实体计数 内置索引计数 内置索引大小 数据大小 复合索引大小 复合索引计数 总大小 但
  • 为什么结构体的 sizeof 不安全

    The MSDN http msdn microsoft com en us library eahchzkf 28v vs 80 29 aspx明确指出 对于所有其他类型 包括结构体 sizeof 运算符只能 在不安全的代码块中使用 Th
  • 在 URLSearchParams 中使用 json 对象

    是否可以以某种方式将 json 对象附加到 URLSearchParams 对象上 所以而不是 urlSearchParams append search person it s urlSearchParams append search
  • 没有为 MySQLi 准备好的语句中的参数提供数据

    我一直在重新设计我的网站 从不受保护的 MySQL 查询到 mysqli 准备好的语句 一切都很顺利 直到我得到这个 没有为准备好的语句中的参数提供数据 if empty err pSETQuery NULL if empty POST p
  • 命名空间中的枚举

    做这样的事情有没有意义 namespace status enum status ok error 并像这样使用它status ok 或者我应该这样做 enum status status ok status error 并像这样使用它st
  • 添加到 ArrayList Java

    我是java初学者 需要一些帮助 我正在尝试将抽象数据类型 Foo 它是一个关联列表 转换为字符串 B 的 Arraylist 如何循环遍历该列表并将每个字符串添加到数组中 我可能想多了 但我现在迷失了 我在这里先向您的帮助表示感谢 实例化
  • deepcopy() 非常慢

    我在 Python 中有一个包含大约 1000 个对象 行星系统 恒星 行星 的游戏状态 我需要复制它并在需要时对其应用一堆转换 然而 在大约 1 个请求 秒的情况下 这是占用了我24 63 的运行时间 https i stack imgu
  • 如何列出属于某个VPC的所有资源?

    在我的 AWS 账户中 我的 VPC 很少 我正在尝试找到一种方法来列出位于某个 VPC 下的所有资源 谢谢 您可以通过三种方式完成此操作 AWS CLI AWS 控制台或代码 AWS CLI 您可以使用 AWS CLI 列出与 VPC 关
  • Slim 基本身份验证

    今天是个好日子 我这里有一个有效的精简代码slim basic auth https packagist org packages tuupola slim basic auth当我进入受限目录时 会显示以下内容 一切正常 但我想做的是将其
  • 使用 SqlDataReader 和字符串数组

    我想使用数据读取器读取记录并将结果发送到数组字符串 我使用存储过程从 2 个表中选择数据 string ReqID string ConnectionString ConfigurationManager ConnectionStrings
  • Extjs如何让滚动条出现?

    我需要在表单比包含容器更宽时立即显示滚动条 我在容器上设置了属性 autoScroll true 但它不起作用 有办法得到我需要的结果吗 这是工作示例 http jsfiddle net mQC3B 2 http jsfiddle net
  • 提高 SQL Server 中的 Xquery 性能

    我有一个 Azure SQL 数据库 其中有 1 个表和大量记录 超过 75 000 条 该表包含 XML 数据类型的列 此列如下所示