Поделиться через


Указание путей и подсказок оптимизации для выборочных XML-индексов

Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure

В этой статье описывается, как указать пути узлов для индексирования и оптимизации при создании или изменении выборочных XML-индексов.

Пути узла и указания по оптимизации задаются одновременно в одной из следующих инструкций:

Дополнительные сведения о выборочных XML-индексах см. в разделе "Выборочные XML-индексы" (SXI).

Общие сведения о типах XQuery и SQL Server в нетипизированном XML

Выборочные XML-индексы поддерживают две системы типов: типы XQuery и типы SQL Server. Индексированный путь можно использовать как для сопоставления выражения XQuery, так и для сопоставления возвращаемого типа метода данных xml.

  • Если путь к индексу не аннотирован или помечен ключевым словом XQUERY, путь соответствует выражению XQuery. Есть два варианта путей узла, аннотированных с помощью XQUERY.

    • Если ключевое слово XQUERY и тип данных XQuery не указаны, используются сопоставления по умолчанию. Обычно производительность и хранение не являются оптимальными.

    • Если было указано ключевое слово XQUERY и тип данных Xquery, а также другие указания по оптимизации (необязательно), вы можете достичь наилучшей возможной производительности и наиболее эффективного хранения. Однако приведение может завершиться ошибкой.

  • Если путь к индексу аннотирован с помощью ключевого слова SQL, то он соответствует возвращаемому типу метода value() типа данных xml. Укажите соответствующий тип данных SQL Server, который является возвращаемым типом, ожидаемым от value() метода.

Существуют тонкие различия между системой XML-типов выражений XQuery и системой типов SQL Server, применяемой к value() методу типа данных XML . Различия следующие:

  • Система типов Xquery учитывает конечные пробелы. Например, в соответствии с семантикой типа XQuery строки abc и abc не равны, а в SQL Server эти строки равны.

  • Типы данных с плавающей запятой Xquery поддерживают специальные значения +/- нуль и +/- бесконечность. Эти специальные значения не поддерживаются в типах данных с плавающей запятой SQL Server.

Типы XQuery в нетипизированном XML

  • Типы XQuery соответствуют выражениям XQuery во всех методах типа данных XML , включая value() метод.

  • Типы XQuery поддерживают такие указания оптимизации: node(), SINGLETON, DATA TYPE и MAXLENGTH.

В выражениях Xquery с нетипизированным XML вы можете выбрать между двумя режимами работы.

  • Режим сопоставления по умолчанию. В этом режиме при создании селективного XML-индекса указывается только путь.

  • Определяемый пользователем режим сопоставления. В этом режиме указывается как путь, так и необязательные указания по оптимизации.

В режиме сопоставления по умолчанию используется консервативный параметр хранения, который всегда является безопасным и общим. Он может быть сопоставлен с любым типом выражения. Ограничение режима сопоставления по умолчанию заключается в недостаточно оптимальной производительности, так как требуется увеличенное число преобразований во время выполнения, и вторичные индексы недоступны.

Ниже приведен пример выборочного XML-индекса, созданного с помощью сопоставлений по умолчанию. Для всех трех путей используются тип узла по умолчанию (xs:untypedAtomic) и кардинальность.

CREATE SELECTIVE XML INDEX example_sxi_UX_default
ON Tbl(xmlcol)
FOR
(
    mypath01 =  '/a/b',
    mypath02 = '/a/b/c',
    mypath03 = '/a/b/d'
);

Пользовательский режим сопоставления позволяет указать тип и мощность для узла, чтобы обеспечить лучшую производительность. Однако это повышение производительности достигается за счет снижения безопасности (поскольку приведение может завершиться ошибкой) и универсальности (поскольку с селективным XML-индексом сопоставляется только определённый тип).

Для нетипизированного XML поддерживаются следующие типы Xquery:

  • xs:boolean
  • xs:double
  • xs:string
  • xs:date
  • xs:time
  • xs:dateTime

Если тип не указан, предполагается, что узел имеет xs:untypedAtomic тип данных.

Отображенный селективный XML-индекс вы можете оптимизировать следующим образом:

CREATE SELECTIVE XML INDEX example_sxi_UX_optimized
ON Tbl(xmlcol)
FOR
(
    mypath= '/a/b' as XQUERY 'node()',
    pathX = '/a/b/c' as XQUERY 'xs:double' SINGLETON,
    pathY = '/a/b/d' as XQUERY 'xs:string' MAXLENGTH(200) SINGLETON
);
-- mypath - Only the node value is needed; storage is saved.
-- pathX - Performance is improved; secondary indexes are possible.
-- pathY - Performance is improved; secondary indexes are possible; storage is saved.

Типы SQL Server в нетипизированном XML

  • Типы SQL Server соответствуют возвращаемому значению метода value().

  • Типы SQL Server поддерживают эту подсказку оптимизации: SINGLETON.

Указание типа является обязательным для путей, возвращающих типы SQL Server. Используйте тот же тип SQL Server, который будет использоваться в методе value() .

Обратите внимание на следующий запрос:

SELECT T.record,
    T.xmldata.value('(/a/b/d)[1]', 'NVARCHAR(200)')
FROM myXMLTable T;

Указанный запрос возвращает значение из пути /a/b/d , упакованного в тип данных NVARCHAR(200), поэтому тип данных, указываемый для узла, является очевидным. Однако нет схемы для указания кардинальности узла в нетипизированном XML. Чтобы указать, что узел d должен встречаться не более одного раза в родительском узле b, создайте селективный XML-индекс, в котором подсказка оптимизации SINGLETON используется следующим образом:

CREATE SELECTIVE XML INDEX example_sxi_US
ON Tbl(xmlcol)
FOR
(
    node1223 = '/a/b/d' as SQL NVARCHAR(200) SINGLETON
);

Общие сведения о поддержке выборочного XML-индекса для типизированного XML

Типизированный XML в SQL Server — это схема, связанная с данным XML-документом. Схема определяет общую структуру документа и типы узлов. Если схема существует, выборочный XML-индекс применяет структуру схемы, когда пользователь продвигает пути, поэтому нет необходимости указывать типы XQUERY для путей.

Селективные XML-индексы поддерживают следующие типы XSD:

  • xs:anyUri
  • xs:boolean
  • xs:date
  • xs:dateTime
  • xs:day
  • xs:decimal
  • xs:double
  • xs:float
  • xs:int
  • xs:integer
  • xs:language
  • xs:long
  • xs:name
  • xs:NCName
  • xs:negativeInteger
  • xs:nmtoken
  • xs:nonNegativeInteger
  • xs:nonPositiveInteger
  • xs:positiveInteger
  • xs:qname
  • xs:short
  • xs:string
  • xs:time
  • xs:token
  • xs:unsignedByte
  • xs:unsignedInt
  • xs:unsignedLong
  • xs:unsignedShort

При создании выборочного XML-индекса в документе, который связан со схемой, указание типа XQuery при создании или изменении индекса приводит к ошибке. Пользователь может использовать аннотации типов SQL в части продвижения пути. Тип SQL должен быть допустимым преобразованием из типа XSD, определенного в схеме, иначе будет выдана ошибка. Поддерживаются все типы SQL, имеющие адекватное представление в XSD, за исключением типов данных даты-времени.

Примечание.

Выборочный индекс используется, если тип, указанный в продвижении пути выборочного XML-индекса, совпадает со значением, возвращаемым методом value().

Следующие указания оптимизации можно использовать с типизированными XML-документами.

  • node() подсказка по оптимизации.

  • Указание оптимизации MAXLENGTH можно использовать с типами xs:string, чтобы сократить индексируемое значение.

Дополнительные сведения об указаниях оптимизации см. в разделе Задание указаний по оптимизации.

Указание путей

Селективный XML-индекс позволяет индексировать только подмножество узлов из сохраненных XML-данных, значимое для запросов, которые планируется выполнять. Когда подмножество значимых узлов намного меньше, чем общее количество узлов в XML-документе, селективный XML-индекс сохраняет только значимые узлы. Для эффективного использования селективного XML-индекса необходимо определить нужное подмножество узлов для индексирования.

Выбор узлов для индексирования

Для определения правильного подмножества узлов можно использовать следующие два принципа, чтобы добавить в селективный XML-индекс.

  1. Принцип 1. Чтобы оценить заданное выражение XQuery, необходимо проиндексировать все узлы, подлежащие изучению.

    • Индексируйте все узлы, существование или значения которых используются в выражении XQuery.

    • Индексируйте все узлы в выражении XQuery, к которым применяются предикаты XQuery.

    Рассмотрим следующий запрос по образцу XML-документа в этой статье:

    SELECT T.record FROM myXMLTable T
    WHERE T.xmldata.exist('/a/b[./c = "43"]') = 1;
    

    Для возвращения экземпляров XML, которые удовлетворяют запросу, селективному XML-индексу необходимо просматривать 2 узла в каждом из экземпляров XML.

    • Узел c, так как его значение используется в выражении XQuery.

    • Узел b, поскольку предикат применяется на узелb в выражении XQuery.

  2. Принцип 2. Для достижения наилучшей производительности проиндексируйте все узлы, необходимые для вычисления заданного выражения XQuery. Если индексировать только некоторые узлы, выборочный XML-индекс улучшает оценку вложенных выражений, включающих только индексированные узлы.

Для улучшения производительности инструкции SELECT, описанной выше, вы можете создать следующий селективный XML-индекс.

CREATE SELECTIVE XML INDEX simple_sxi
ON Tbl(xmlcol)
FOR
(
    path123 =  '/a/b',
    path124 =  '/a/b/c'
);

Индекс идентичных путей

Вы не можете обозначить одинаковые пути как один и тот же тип данных под разными именами путей. Например, следующий запрос вызывает ошибку, поскольку pathOne и pathTwo идентичны.

CREATE SELECTIVE INDEX test_simple_sxi ON T1(xmlCol)
FOR
(
    pathOne = 'book/authors/authorID' AS XQUERY 'xs:string',
    pathTwo = 'book/authors/authorID' AS XQUERY 'xs:string'
);

Однако вы можете использовать одинаковые пути как разные типы данных с разными именами. Например, следующий запрос теперь является допустимым, поскольку типы данных отличаются:

CREATE SELECTIVE INDEX test_simple_sxi ON T1(xmlCol)
FOR
(
    pathOne = 'book/authors/authorID' AS XQUERY 'xs:double',
    pathTwo = 'book/authors/authorID' AS XQUERY 'xs:string'
);

Примеры

Ниже приведены несколько примеров выбора правильных узлов для индексирования для различных типов XQuery.

Пример 1

Вот простой XQuery, использующий exist() метод:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b/c/d/e/h') = 1;

В следующей таблице показаны узлы, которые должны быть индексированы для того, чтобы данный запрос мог использовать селективный XML-индекс.

Узел, который необходимо включить в индекс Причина для индексирования этого узла
/a/b/c/d/e/h Существование узла h оценивается в методе exist() .

Пример 2

Ниже приведен более сложный вариант предыдущего XQuery с примененным предикатом:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b/c/d/e[./f = "SQL"]') = 1;

В следующей таблице показаны узлы, которые должны быть индексированы для того, чтобы данный запрос мог использовать селективный XML-индекс.

Узел, который необходимо включить в индекс Причина для индексирования этого узла
/a/b/c/d/e Предикат применяется для узла e.
/a/b/c/d/e/f Значение узла f вычисляется внутри предиката.

Пример 3

Ниже приведен более сложный запрос с предложением value() :

SELECT T.record,
    T.xmldata.value('(/a/b/c/d/e[./f = "SQL"]/g)[1]', 'nvarchar(100)')
FROM myXMLTable T;

В следующей таблице показаны узлы, которые должны быть индексированы для того, чтобы данный запрос мог использовать селективный XML-индекс.

Узел, который необходимо включить в индекс Причина для индексирования этого узла
/a/b/c/d/e Предикат применяется для узла e.
/a/b/c/d/e/f Значение узла f вычисляется внутри предиката.
/a/b/c/d/e/g Значение узла g возвращается методом value() .

Пример 4

Ниже приведен запрос, использующий предложение FLWOR внутри exist() предложения. (Имя FLWOR образуется из 5 предложений, которые могут составлять выражение FLWOR в XQuery: for, let, where, order by и return.)

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('
  For $x in /a/b/c/d/e
  Where $x/f = "SQL"
  Return $x/g
') = 1;

В следующей таблице показаны узлы, которые должны быть индексированы для того, чтобы данный запрос мог использовать селективный XML-индекс.

Узел, который необходимо включить в индекс Причина для индексирования этого узла
/a/b/c/d/e Наличие узла e вычисляется в предложении FLWOR.
/a/b/c/d/e/f Значение узла f вычисляется в предложении FLWOR.
/a/b/c/d/e/g Существование узла g вычисляется методом exist() .

Указание советов по оптимизации

Необязательные указания оптимизации вы можете использовать для указания дополнительных подробностей сопоставления для узла, индексированного селективным XML-индексом. Например, вы можете указать тип данных, количество элементов узла, а также некоторые сведения о структуре данных. Эта дополнительная информация поддерживает более эффективное сопоставление. Она также позволяет получить улучшение производительности, эффективности хранения или и того и другого.

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

Некоторые указания по оптимизации, такие как указание SINGLETON, вводят ограничения для ваших данных. В некоторых случаях ошибки могут возникать, если эти ограничения не выполнены.

Преимущества подсказок оптимизации

В следующей таблице приведены указания по оптимизации, которые поддерживают более эффективное хранение или улучшение в производительности.

Указание по оптимизации Более эффективное хранение Улучшение производительности
node() Да Нет
Синглтон Нет Да
DATA TYPE Да Да
MAXLENGTH Да Да

Указания по оптимизации и типы данных

Узлы можно индексировать как типы данных XQuery или как типы данных SQL Server. В следующей таблице показано, какие указания оптимизации поддерживаются для каждого типа данных.

Указание по оптимизации Типы данных XQuery Типы данных SQL
node() Да Нет
SINGLETON Да Да
DATA TYPE Да Нет
MAXLENGTH Да Нет

Указание по оптимизации node()

Область применения: типы данных XQuery

Вы можете использовать node() оптимизацию для указания узла, значение которого не требуется для оценки типичного запроса. Это указание снижает требования к хранилищу, поскольку обычному запросу необходимо вычислить только существование узла. (По умолчанию селективный XML-индекс хранит значения всех повышенных узлов, за исключением сложных типов узлов.)

Рассмотрим следующий пример:

SELECT T.record FROM myXMLTable T
WHERE T.xmldata.exist('/a/b[./c=5]') = 1;

Для использования селективного XML-индекса для оценки этого запроса повысьте узлы b и c. Однако, так как значение узла b не требуется, можно использовать node() указание со следующим синтаксисом:

`/a/b/ as node()

Если запросу требуется значение узла, индексированного с node() указанием, нельзя использовать выборочный XML-индекс.

Рекомендация по оптимизации SINGLETON

Область применения: типы данных XQuery или SQL Server

Подсказка по оптимизации с помощью SINGLETON указывает кардинальность узла. Это указание улучшает производительность запросов, так как заранее известно, что узел появляется не более одного раза в своем родителе или предках.

Рассмотрим пример XML-документа в этой статье.

Для использования селективного XML-индекса в запросе к этому документу вы можете задать указание SINGLETON для узла d , поскольку он встречается максимум один раз в его родительском элементе.

Если было задано указание SINGLETON, а узел встречается более одного раза в его родителе или предке, то при создании индекса (для существующих данных) или при выполнении запроса (для новых данных) возникнет ошибка.

Подсказка по оптимизации DATA TYPE

Область применения: типы данных XQuery

Указание оптимизации ТИПА ДАННЫХ позволяет указать XQuery или тип данных SQL Server для индексированного узла. Тип данных используется для столбца в таблице данных селективного XML-индекса, соответствующего индексированному узлу.

При приведение существующего значения к указанному типу данных завершается ошибкой, операция вставки (в индекс) не завершается ошибкой; однако значение NULL вставляется в таблицу данных индекса.

Подсказка по оптимизации MAXLENGTH

Область применения: типы данных XQuery

Указание по оптимизации MAXLENGTH позволяет ограничить длину данных xs:string. MAXLENGTH не относится к типам данных SQL Server, так как вы указываете длину при указании типов дат VARCHAR или NVARCHAR.

Если существующая строка длиннее заданного значения MAXLENGTH, вставка этой строки в индекс терпит неудачу.

Пример XML-документа для примеров

В примерах этой статьи ссылается следующий пример XML-документа:

<a>
    <b>
         <c atc="aa">10</c>
         <c atc="bb">15</c>
         <d atd1="dd" atd2="ddd">md </d>
    </b>
     <b>
        <c></c>
        <c atc="">117</c>
     </b>
</a>

См. также