Как переписать SQL-запрос xpath, чтобы иметь возможность создавать индексированное представление - PullRequest
4 голосов
/ 27 ноября 2011

У меня есть представление, которое извлекает некоторую информацию из таблицы с данными 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 ]

1 голос
/ 28 ноября 2011
Is it possible to rewrite the view to make it possible to add an index?

Нет. Я так не думаю. Вместо этого я собираюсь использовать некоторую информацию из этого вопроса и предложить другой способ.

Вы можете добавить вычисляемый постоянный столбец к вашей таблице, который содержит только тот 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]

Запрос на получение идентификаторов:

;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, но вы говорите мне. Конечно, у меня нет возможности проверить это без ваших данных.

0 голосов
/ 27 ноября 2011

Вы пробовали индекс XML?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...