如何重写SQL xpath查询以便能够创建索引视图

时间:2011-11-27 18:27:53

标签: sql sql-server-2008 xpath view indexing

我有一个视图,用xml数据从表中提取一些信息 每个文档包含一个Product和几个PurchaseOrderDetail。我想为每个PurchaseOrderDetail创建一个包含所有Product的视图。

CREATE VIEW [dbo].[XML_PurchaseOrders]
WITH SCHEMABINDING
AS
    SELECT
    p.n.value('.', 'int') AS PurchaseOrderID
    ,x.ProductID
    FROM dbo.XmlLoadData x
    CROSS APPLY x.PayLoad.nodes('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest"; 
    /NS:ProductAndRelated/NS:Product/NS:PurchaseOrderDetails/NS:PurchaseOrderDetail/NS:PurchaseOrderID') p(n)
GO

PayLoad列包含XML数据。

这种观点存在的问题是,由于XML文档既庞大又丰富,因此速度非常慢。

我想索引此视图,但这给了我错误

  

无法在视图“XmlLoad.dbo.XML_PurchaseOrders”上创建索引,因为它包含APPLY。考虑不对视图编制索引,或者删除APPLY。

是否可以重写视图以便添加索引?

我尝试了多次尝试,主要是使用select ... from (select ....) innnerSelect group by foo,但是所有这些尝试都落在了关于视图索引的一条或另一条规则上。

2 个答案:

答案 0 :(得分:1)

Is it possible to rewrite the view to make it possible to add an index?

没有。我不这么认为。相反,我将使用this问题中的一些信息并提出另一种方式。

您可以向表中添加计算的持久列,该列仅包含具有id的XML。不允许在计算列中直接使用XQUERY内容,但您可以使用用户定义的函数来执行此操作。

这是功能:

create function dbo.GetPurchaseOrderID(@XMLData xml) 
returns xml with schemabinding
as
begin
  return @XMLData.query('declare namespace NS="http://schemas.datacontract.org/2004/07/XmlDbPerfTest"; 
    /NS:ProductAndRelated/NS:Product/NS:PurchaseOrderDetails/NS:PurchaseOrderDetail/NS:PurchaseOrderID')
end 

使用持久XML列创建表:

CREATE TABLE [dbo].[XmlLoadData](
    [ProductID] [int] NOT NULL identity,
    [PayLoad] [xml] NOT NULL,
    [Size]  AS (len(CONVERT([nvarchar](max),[PayLoad],0))),
    [PurchaseOrderIDs] AS dbo.GetPurchaseOrderID(PayLoad) PERSISTED,
 CONSTRAINT [PK_XmlLoadData] PRIMARY KEY CLUSTERED 
(
    [ProductID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
       ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

查询以获取ID:

;with xmlnamespaces('http://schemas.datacontract.org/2004/07/XmlDbPerfTest' as NS)
select ProductID,
       P.N.value('.', 'int') as PurchaseOrderID
from XmlLoadData
  cross apply PurchaseOrderIDs.nodes('NS:PurchaseOrderID') as P(N)

我的有限测试表明它有点快。如果您的XML文档很大,那么它应该是一个更大的改进。我怀疑它会提高1000倍的性能,因为你仍在处理解释XML,但你告诉我。如果没有您的数据,我当然无法进行测试。

答案 1 :(得分:0)