1

以下查询需要很长时间才能返回结果。我已经尝试了我能想到的一切来优化查询。使用这种结构存储了大约 10000 行 xml,大约需要 2.5 分钟才能返回结果。我在表上设置了一个主 xml 索引,并在表上设置了一个辅助(属性)索引。我已将索引设置为每 7 天重建一次。

我参考了这些位置

XML 数据类型的性能优化

使用 xml 数据类型方法的指南

Xml 索引指南

索引 XML

XML 最佳实践

任何意见和建议将不胜感激。

对不起所有的代码,如果不需要,我可以把它拿出来。

我有一张桌子:

CREATE TABLE [dbo].[XmlTable](
    [XmlId] [int] IDENTITY(1,1) NOT NULL,
    [XmlDocument] [xml] NOT NULL,
 CONSTRAINT [PK_XmlTable] PRIMARY KEY CLUSTERED 
(
    [XmlId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

带有属性二级索引

SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET NUMERIC_ROUNDABORT OFF

GO

CREATE XML INDEX [IXML_XmlTable_XmlDocument_Property] ON [dbo].[XmlTable]
(
    [XmlDocument]
)
USING XML INDEX [PXML_XmlTable_XmlDocument] FOR PROPERTY WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

带有主索引

SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET NUMERIC_ROUNDABORT OFF

GO


CREATE PRIMARY XML INDEX [PXML_XmlTable_XmlDocument] ON [dbo].[XmlTable]
(
    [XmlDocument]
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

使用这样的结构:

<dev:Doc xmlns:dev="http://www.w3.org/2001/XMLSchema" SchemaVersion="0.1" Settings="Testing" Title="Ordering">
  <dev:Base RevisionNumber="0" Baseid="34433" />
  <dev:Rev Time="2013-01-21T15:08:00">
    <dev:Person Name="Me" Systemid="54654" />
  </dev:Rev>
  <dev:Functions Id="A1">
    <dev:A1 Number="1">
      <dev:Codes>D</dev:Codes>
      <dev:Required>true</dev:Required>
      <dev:Informational>false</dev:Informational>
      <dev:Visitors>
        <dev:Visitor Name="Dev01" Location="STLRF">
          <dev:Divisions>
            <dev:Division Number="1" Name="TFR3" Usage="Monitor">
              <dev:Description>Development Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="2" Name="DEF32" Usage="Monitor">
              <dev:Description>Testing Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="3" Name="DEP13" Usage="None">
              <dev:Description>Guided Fundamentals</dev:Description>
            </dev:Division>
          </dev:Divisions>
        </dev:Visitor>
        <dev:Visitor Name="Dev02" Location="STLRF">
          <dev:Divisions>
            <dev:Division Number="1" Name="TFR3" Usage="Monitor">
              <dev:Description>Development Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="2" Name="DEF32" Usage="Monitor">
              <dev:Description>Testing Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="3" Name="DEP13" Usage="None">
              <dev:Description>Guided Fundamentals</dev:Description>
            </dev:Division>
          </dev:Divisions>
        </dev:Visitor>
        <dev:Visitor Name="Dev03" Location="FGRTY">
          <dev:Divisions>
            <dev:Division Number="1" Name="TFR3" Usage="Monitor">
              <dev:Description>Development Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="2" Name="DEF32" Usage="Monitor">
              <dev:Description>Testing Fundamentals</dev:Description>
            </dev:Division>
            <dev:Division Number="3" Name="DEP13" Usage="None">
              <dev:Description>Guided Fundamentals</dev:Description>
            </dev:Division>
          </dev:Divisions>
        </dev:Visitor>
      </dev:Visitors>
      <dev:Senders>
        <dev:Sender Name="FGY(14A)" />
      </dev:Senders>
    </dev:A1>
  </dev:Functions>
  <dev:Functions Id="A2">
    <dev:A2 Number="1">
      <dev:Codes>C</dev:Codes>
      <dev:Required>true</dev:Required>
      <dev:Informational>false</dev:Informational>
      <dev:Remarks>Support</dev:Remarks>
      <dev:Notes>Ready</dev:Notes>
      <dev:Visitors>
        <dev:Visitor Name="GHFF">
          <dev:Divisions>
            <dev:Division Number="0" Name="Trial" Usage="None">
              <dev:FromLocation>LOPO</dev:FromLocation>
              <dev:ToLocation>RDSS</dev:ToLocation>
              <dev:Description>Rich Filter</dev:Description>
            </dev:Division>
          </dev:Divisions>
        </dev:Visitor>
      </dev:Visitors>
      <dev:Senders>
        <dev:Sender Name="W33R" />
      </dev:Senders>
      <dev:IsReady>true</dev:IsReady>
      <dev:IsCall>false</dev:IsCall>
    </dev:A2>
    <dev:A2 Number="2">
      <dev:Codes>A</dev:Codes>
      <dev:Required>true</dev:Required>
      <dev:Informational>false</dev:Informational>
      <dev:Remarks>Loader Ready</dev:Remarks>
      <dev:Notes>Ready</dev:Notes>
      <dev:Visitors>
        <dev:Visitor Name="UDT">
          <dev:Divisions>
            <dev:Division Number="0" Name="Trial" Usage="None">
              <dev:FromLocation>TYUJ</dev:FromLocation>
              <dev:ToLocation>DETF</dev:ToLocation>
              <dev:Description>Web Enhance</dev:Description>
            </dev:Division>
          </dev:Divisions>
        </dev:Visitor>
      </dev:Visitors>
      <dev:Senders>
        <dev:Sender Name="RJ4" />
      </dev:Senders>
      <dev:IsReady>true</dev:IsReady>
      <dev:IsCall>false</dev:IsCall>
    </dev:A2>
  </dev:Functions>
</dev:Doc>

和查询:

;WITH XMLNAMESPACES (Default 'http://www.w3.org/2001/XMLSchema' )
SELECT  

a.value('@RevisionNumber[1]', 'INT') AS Number,
b.value('@Id[1]', 'VARCHAR(10)') AS FunctionID,
c.value('@Number[1]', 'INT') AS Number,
d.value('@Name[1]', 'VARCHAR(10)') AS Visitor,
d.value('@Location[1]', 'VARCHAR(10)') AS Location,
e.value('@Name[1]', 'NVARCHAR(10)') AS Sender

From XmlTable as x

    CROSS APPLY xmlDocument.nodes('Doc/Base') As aa(a)
    CROSS APPLY xmlDocument.nodes('Doc/Functions') bb(b)
    CROSS APPLY b.nodes('*') cc(c)
    CROSS APPLY c.nodes('Visitors/Visitor') dd(d)
    CROSS APPLY c.nodes('Senders/Sender') ee(e)

这是表格中的插入内容,为了测试我运行了 10000 次

INSERT INTO XmlTable(XMLDocument)
SELECT * FROM OPENROWSET(
   BULK 'C:\Users\123\Desktop\Practice.xml',
   SINGLE_BLOB) AS x;

Go 10000

我最初是这个查询,但它比上面的查询慢 x3

;WITH XMLNAMESPACES (default 'http://www.w3.org/2001/XMLSchema')
SELECT  
    a.value('(Base/@RevisionNumber)[1]', 'INT') AS RevNumber,
    b.value('@Id[1]', 'VARCHAR(10)') AS FunctionID,
    c.value('@Number[1]', 'INT') AS Number,
    d.value('@Name[1]', 'VARCHAR(10)') AS Visitor,
    d.value('@Location[1]', 'VARCHAR(10)') AS Location,
    c.value('(Senders/Sender/@Name)[1]', 'VARCHAR(10)') AS Sender
FROM XmlTable
CROSS APPLY xmlDocument.nodes('Doc') As aa(a)
CROSS APPLY a.nodes('Functions') bb(b)
CROSS APPLY b.nodes('*') cc(c)
CROSS APPLY c.nodes('Visitors/Visitor') dd(d)
4

1 回答 1

2

首先,看起来你正在做很多交叉申请来切碎。你能不能仅仅扩展一个单一的交叉申请一个共同的分母并获得你的价值,比如:

a.value('/(element)/(element)[(expression)].value('(@thing)', '(type)').

我的想法是您拥有的语法很好,但是您以五次不同的方式创建了一个层次结构,然后多次交叉应用它。我没有做很多 xml 粉碎,但我知道多重交叉应用可能是杀手,因为你采用一个 3D 值并以不同方式填充参考五次可能是问题所在。您可以使用 '/(element)' 表示法进一步扩展元素。

我可能是错的,这可能很好。如果你必须做这么多的交叉应用,你可以先在临时表转储中做它们可能会加速它。然后,您可能也可以在临时表上创建 xml 索引。例如:

Select a.query('*')
into #NodeA
From XmlTable as x
    CROSS APPLY xmlDocument.nodes('Doc/Base') As aa(a)

如果在删除临时表后性能仍然很慢,那么创建一个 xml 索引。不确定 xml 索引,因为我还没有完成它们。我知道您可以在临时表上删除和创建常规索引,所以我假设您可以使用 xml 索引来完成。

http://msdn.microsoft.com/en-us/library/bb934097.aspx

编辑

请记住,您还可以在粉碎 xml 时将“查询”语法与“值”语法混合使用,这对于查找树结构然后填充结果非常有用。我在 SSRS 报告服务器中粉碎 xml 时这样做,类似于:

Use ReportServer
GO

With a as 
                (
                Select 
                                c.Name as ReportName
                ,               cast(sub.ExtensionSettings as xml) XML
                ,               sub.ModifiedDate as SubscriptionModifiedDate
                ,               sub.Description
                ,               sub.LastRunTime
                from dbo.ReportSchedule rs (nolock) 
                                join dbo.Schedule s (nolock) on rs.ScheduleID = s.ScheduleID
                                join dbo.Subscriptions sub (nolock) on rs.SubscriptionID = sub.SubscriptionID
                                join dbo.Catalog c (nolock) on rs.ReportID = c.ItemID
                )
select 
                a.ReportName
,               a.SubscriptionModifiedDate
,               a.Description
,               t.query('/ParameterValues/ParameterValue[* = "Subject"]/Value').value('.', 'varchar(max)') as Subject
from a
    cross apply a.XML.nodes('//ParameterValues') as n(t)
于 2013-04-18T16:28:01.403 回答