【问题标题】:How to rewrite SQL xpath query to be able to create an indexed view如何重写 SQL xpath 查询以创建索引视图
【发布时间】:2012-01-07 10:40:10
【问题描述】:

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

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,但所有这些都落在了关于视图索引的一个或另一个规则上。

【问题讨论】:

  • 由于您需要使用 XML 中的多个节点,我看不出没有CROSS APPLY 怎么办你可以在它上面创建一个索引视图:-(
  • @marc_s,我也没有,但我希望有其他方法来扩展我不知道的 XML。
  • 我认为没有选项可以从 XML 中提取这些数据并存储在关系表中?
  • @billinkc,这就是我目前正在做的事情。但最好有一个索引视图以避免维护其他表并确保关系表不会与主表不同步。

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


【解决方案1】:
Is it possible to rewrite the view to make it possible to add an index?

没有。我不这么认为。相反,我将使用来自this question 的一些信息并提出另一种方法。

您可以将计算的持久列添加到仅包含具有 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,但您告诉我。如果没有你的数据,我当然无法测试。

【讨论】:

  • 这听起来很有趣。我想我可以使用一个函数来构建一个精简版本的 XML,其中只包含视图所需的数据(在现实生活中,我拥有的数据多于一项)。然后我可以从那个最小的 XML 创建我的视图。
【解决方案2】:

【讨论】:

  • 不能选择 XML 索引。它至少增加了 10GB 的数据库大小,而且我们经常通过网络处理数据库副本。我只想索引 XML 数据中的一小部分内容。 xml文档很大很多。
  • 我还在较小的数据子集上尝试了 XML 索引,但改进只有大约 2 倍。我需要 1000 倍左右。
猜你喜欢
  • 2018-01-05
  • 2014-09-14
  • 2011-04-25
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多