Вторичные XML-индексы
Для повышения производительности поиска можно также создать вторичные XML-индексы. Перед созданием вторичных индексов должен существовать первичный XML-индекс. Существуют следующие типы вторичных индексов:
вторичный индекс PATH типа данных XML;
вторичный индекс VALUE типа данных XML;
вторичный индекс PROPERTY типа данных XML.
Ниже приведены некоторые рекомендации по созданию вторичных индексов.
Если при работе с XML-столбцами часто используются выражения пути, вторичный XML-индекс PATH, скорее всего, ускорит обработку данных. Типичный пример — выполнение метода exist() для XML-столбцов в предложении WHERE инструкции Transact-SQL.
Если с использованием выражений пути извлекаются множественные значения из отдельных экземпляров XML, может принести пользу кластеризация путей в пределах каждого экземпляра XML в индекс PROPERTY. Этот сценарий обычно имеет место при работе с наборами свойств, когда извлекаются свойства объекта и известно значение его первичного ключа.
Если запрашиваются значения экземпляров XML, не зная имен элементов или атрибутов, содержащих эти значения, следует подумать о создании индекса VALUE. Как правило, это имеет место при уточняющем запросе по осям нижних уровней (например, //author[last-name="Howard", где элементы <author> могут встречаться на любом уровне иерархии). Кроме того, такая ситуация встречается при обработке запросов с символами-шаблонами (например, /book [@* = "novel"], где в запросе выполняется поиск элементов <book>, имеющих некоторый атрибут со значением «novel»).
Вторичный индекс PATH типа данных XML
Если обычно запросы задают выражения пути для столбцов типа данных xml, вторичный индекс PATH может ускорить их поиск. Как ранее отмечалось, первичный индекс полезен в тех запросах, где метод exist() указан в предложении WHERE. Добавление вторичного индекса PATH может еще более повысить производительность поиска в таких запросах.
Хотя первичный XML-индекс позволяет избежать на стадии выполнения запроса разбора больших двоичных объектов типа данных XML, он не в состоянии обеспечить максимальную производительность запросов на основе выражений пути. Так как все строки первичного XML-индекса, соответствующие большому двоичному объекту XML, просматриваются последовательно, такой поиск работает довольно медленно. В таких случаях наличие вторичного индекса, построенного для значений путей и узлов первичного индекса, может существенно ускорить поиск в нем. Во вторичном индексе PATH значения пути и узлов являются ключевыми столбцами, позволяющими выполнять более эффективный поиск путей. Оптимизатор запросов может использовать индекс PATH, например для следующих выражений:
- /root/Location, что задает только путь
или
- /root/Location/@LocationID[.="10"], где заданы как значение пути, так и значение узла.
Следующий запрос демонстрирует, при каких условиях может быть полезен индекс PATH:
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS "PD")
SELECT CatalogDescription.query('
/PD:ProductDescription/PD:Summary
') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist ('/PD:ProductDescription/@ProductModelID[.="19"]') = 1
В этом запросе в методе exist() выражение пути /PD:ProductDescription/@ProductModelID и значение "19" соответствуют ключевым полям индекса PATH. Это позволяет выполнять поиск непосредственно в индексе PATH и при этом обеспечивает более высокую производительность, чем при последовательном переборе значений пути в первичном индексе.
Вторичный индекс VALUE типа данных XML
Если запрос основан на значении, например: /Root/ProductDescription/@*[. = "Mountain Bike"] или //ProductDescription[@Name = "Mountain Bike"], и если путь задан не полностью либо он включает в себя символ-шаблон, скорость выполнения запросов можно повысить, построив вторичный XML-индекс по значениям узлов первичного XML-индекса.
Ключевые столбцы индекса VALUE (значение узла и значение пути) содержатся в первичном XML-индексе. Индекс VALUE может оказаться полезным в тех случаях, если рабочая нагрузка включает в себя запросы значений из экземпляров XML, для которых неизвестны имена элементов или атрибутов, содержащих эти значения. Например, следующее выражение при наличии индекса VALUE выполняется более эффективно:
//author[LastName="someName"], где известно значение элемента <LastName>, но родительский элемент <author> может находиться где угодно;
/book[@* = "someValue"], где запрос выполняет поиск элемента <book> с каким-либо атрибутом, имеющим значение "someValue".
Следующий запрос возвращает столбец ContactID из таблицы Contact. Предложение WHERE задает фильтр, выполняющий поиск значений в столбце AdditionalContactInfo типа xml. Идентификаторы контактов возвращаются только тогда, когда соответствующий большой двоичный объект XML, содержащий дополнительные контактные данные, включает в себя определенный номер телефона. Поскольку элемент <telephoneNumber> может находиться в любом месте XML-документа, выражение пути задает ось descendent-or-self.
WITH XMLNAMESPACES (
'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo' AS CI,
'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes' AS ACT)
SELECT ContactID
FROM Person.Contact
WHERE AdditionalContactInfo.exist('//ACT:telephoneNumber/ACT:number[.="111-111-1111"]') = 1
В этой ситуации искомое значение атрибута <number> известно, но оно может находиться в любом месте экземпляра XML как дочерний элемент элемента <telephoneNumber>. Производительность запроса такого рода может повыситься при поиске указанного значения по индексу.
Вторичный индекс PROPERTY
Производительность запросов, извлекающих одно или несколько значений из отдельных экземпляров XML, может повыситься при использовании индекса PROPERTY. Это происходит при извлечении свойств объекта методом value() типа данных xml, когда для объекта известно значение первичного ключа.
Индекс PROPERTY строится по столбцам (PK, Path и значении узла) первичного XML-индекса, где PK — это первичный ключ базовой таблицы.
Например, для модели продукта 19 следующий запрос извлекает значения атрибутов ProductModelID и ProductModelName при помощи метода value(). Если вместо первичного или вторичных XML-индексов использовать индекс PROPERTY, это может повысить скорость выполнения запросов.
WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' AS "PD")
SELECT CatalogDescription.value('(/PD:ProductDescription/@ProductModelID)[1]', 'int') as ModelID,
CatalogDescription.value('(/PD:ProductDescription/@ProductModelName)[1]', 'varchar(30)') as ModelName
FROM Production.ProductModel
WHERE ProductModelID = 19
За исключением отличий, описанных ниже в этом подразделе, создание XML-индекса для столбца типа xml аналогично созданию индекса для столбца типа данных, отличного от xml. Для создания XML-индексов и управления ими могут использоваться следующие DDL-инструкции Transact-SQL: