【问题标题】:Xml select query xpath is slowxml选择查询xpath很慢
【发布时间】:2012-11-08 13:26:08
【问题描述】:

我的 XML 结构:

<Items>
  <Item>
    <guid>FC550573-7171-997F-752D-8D65590CBFD6</guid>
    <Objects>
       <Object>
         <type>0</type>
         <guid>E10D9DA9-2C8D-8024-2F07-DF21395811BF</guid>
       </Object>
       <Object>
         <type>0</type>
         <guid>D8338400-35C7-781E-A039-C0FDDF80714A</guid>
       </Object>
    </Objects>
  </Item>
</Items>

填充对象表时:

CREATE TABLE [dbo].[Objects](
    [item_guid] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [type] [int] NOT NULL,
    [guid] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY]

使用查询:

INSERT INTO [dbname].[dbo].[Objects]
           ([item_guid]
           ,[type]
           ,[guid])
SELECT
 X.source.query('../../guid').value('.','VARCHAR(36)') as item_guid,
 X.source.query('type').value('.','INT') as type,
 X.source.query('guid').value('.','VARCHAR(36)') as guid
FROM(
Select xmldata from XmlFiles where fullpath=@fp
) AS T(x)
CROSS APPLY x.nodes('Items/Item/Objects/Object') As X(source)

这一行使查询非常慢:

X.source.query('../../guid').value('.','VARCHAR(36)') as item_guid

这里的正确方法是什么?

【问题讨论】:

  • 好吧,首先——您不需要X.source.query('type').value('.','INT')——将它写成X.source.value('(type)[1]', 'INT') 会容易得多,并为您正在评估的每一列节省至少一个XQuery 操作。 ...
  • 为什么您将 GUID 存储为 varchar(36) 列类型?最好的办法是使用 UNIQUEIDENTIFIER - 本机 SQL Server Guid 类型。或者,如果你不能,无论出于何种原因——那么至少使用char(36),因为它总是正好是 36 个字符——“var”部分是完全没有必要的(而且只会产生开销.. .)
  • 感谢您的帮助,WHY 是我是一个 SQL 白痴,作为一个白痴,我试图避免可能与其他列类型一起出现的未知陷阱/约束并使用我熟悉的东西,而我原型这个黑客:) 顺便说一句,我在 xml 中有一个无限长度的字段,varchar(MAX) 是否将 ALL 放在 TEXT 列?

标签: sql sql-server xml tsql sqlxml


【解决方案1】:

使用/text() 获取值有利于非类型化 XML 的性能。使用父轴../.. 也可能很糟糕(正如@marc_s 建议的那样)。

这是一个带有额外交叉应用和/text() 以获取值的版本。​​

试试这个:

select T2.N.value('(guid/text())[1]', 'uniqueidentifier') as item_guid,
       T3.N.value('(type/text())[1]', 'int') as type,
       T3.N.value('(guid/text())[1]', 'uniqueidentifier') as guid
from (SELECT xmldata FROM dbo.XmlFiles WHERE fullpath = @fp) as T1(N)
  cross apply T1.N.nodes('Items/Item') as T2(N)
  cross apply T2.N.nodes('Objects/Object') as T3(N)

你必须判断哪个查询对你来说是最快的。

【讨论】:

  • 非常感谢,text() 改进了很多,然后交叉应用比 text() 做得更多(我也有层次结构,所以我有很多 ../../ 试图把它放在一张桌子上)。我有大量的 XML,从(5 分钟> 到 3 秒)
  • 哇,text() 太棒了。在我们的例子中,它发生了巨大的变化(从几分钟到不到一秒)。很棒的建议!
【解决方案2】:

我只想补充一点,以防其他人遇到这种情况,添加以下选项会产生巨大的影响。

OPTION (OPTIMIZE FOR (@testXml = NULL))

如果您想自己测试,这里有一个我正在运行的简短测试脚本。只需查看这些之间的估计子树成本。

declare @testXml xml set @testXml = '<filters><filter name="test name" type="GREATERTHAN">1</filter><filter name="CLAIMID" type="GREATERTHAN">1</filter></filters>'


select x.value('@name','nvarchar(100) ') filtername, 
x.value('.','nvarchar(200)')filtervalue, 
x.value('@type','nvarchar(50) ') filtertype 
from @testXml.nodes('/filters/filter') as ref(x)
--vs...
select x.value('@name','nvarchar(100) ') filtername,  
x.value('.','nvarchar(200)')filtervalue,  
x.value('@type','nvarchar(50) ') filtertype 
from @testXml.nodes('/filters/filter') as ref(x) 
OPTION (OPTIMIZE FOR (@testXml = NULL))

【讨论】:

  • 另一个小更新。 SQL 2016/17 似乎改变了这些查询提示的功能。用途:优化未知
【解决方案3】:

试试这个,

我们将创建一个临时表变量来存储这个xml值并插入到相应的表对象

//..Xml value to temp variable
Declare @x xml ='<Items><Item><guid>FC550573-7171-997F-752D-8D65590CBFD6</guid><Objects><Object>
                 <type>0</type><guid>E10D9DA9-2C8D-8024-2F07-DF21395811BF</guid></Object><Object>
                 <type>0</type><guid>D8338400-35C7-781E-A039-C0FDDF80714A</guid></Object></Objects>
                 </Item></Items>';

Declare @Temp_Tbl table (RowId int identity, item_guid nvarchar(36), [type] int, [guid] nvarchar(36));

Insert into @Temp_Tbl SELECT @x.value('(/Items/Item/guid)[1]', 'nvarchar(36)'),
   Cont.value('(type)[1]', 'int'),  Cont.value('(guid)[1]', 'nvarchar(36)')                                                                                     
   FROM @x.nodes('/Items/Item/Objects/Object') AS Obj(Cont);

INSERT INTO [dbo].[Objects] Select item_guid,[type],[guid] from @Temp_Tbl;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    相关资源
    最近更新 更多