我有一个视图,用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
,但是所有这些尝试都落在了关于视图索引的一条或另一条规则上。
答案 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)