In part 1 of this series, we tried a simple example from the Books Online without any SXI index at all, and an SXI with all the paths covered. No XEvents were emitted in either case. Now let’s change the XSI around (by dropping and recreating, although we could use ALTER, so envision a drop in between each example) to see what triggers the XEvents and what the query plan effects are.

— first let’s back off one path
CREATE SELECTIVE XML INDEX simple_sxi ON Tbl(xmlcol)
FOR (
path123 =  ‘/a/b’ as XQUERY ‘node()’
— path124 =  ‘/a/b/c’
);

— now, you get XML Reader, XML Reader with XPath Filer, CI Seek on SIDX, CI Scan on base table
— and “selective_xml_index_path_not_indexed” XEvent for /a/b/c
SELECT T.id FROM tbl T WHERE T.xmlcol.exist(‘/a/b[c = “43”]’) = 1

— how about adding the SINGLETON keyword and XQuery Type?
CREATE SELECTIVE XML INDEX simple_sxi ON Tbl(xmlcol)
FOR (
path123 =  ‘/a/b’ as XQUERY ‘node()’,
path124 =  ‘/a/b/c’ as XQUERY ‘xs:string’ SINGLETON
);

— now, you get a single CI Seek on SIDX and CI Scan on base table
SELECT T.id FROM tbl T WHERE T.xmlcol.exist(‘/a/b[c = “43”]’) = 1

— how about an XML.value query instead of XML.exists?
— get XML Reader with XPath Filter, XML Reader, and CI Scan on base table
— and “selective_xml_index_no_compatible_sql_type” XEvent for /a/b/c
SELECT T.id FROM tbl T WHERE T.xmlcol.value(‘(/a/b/c)[1]’, ‘nvarchar(10)’) = ’43′;

— For this to use SXI, we need:
ALTER INDEX simple_sxi ON Tbl FOR (add path124s = ‘/a/b/c’ as SQL nvarchar(10) SINGLETON);

— SXI CI Seek and CI Scan on base table, no XEvents
SELECT T.id FROM tbl T WHERE T.xmlcol.value(‘(/a/b/c)[1]’, ‘nvarchar(10)’) = ’43′;

BTW, if you use ‘varchar(10)’ rather than ‘nvarchar(10)’ in the query, the SXI won’t be used. One last one, let’s see if the SXI will be used if we specify an incorrect XQuery type:

CREATE SELECTIVE XML INDEX simple_sxi ON Tbl(xmlcol)
FOR (
path123 =  ‘/a/b’ as XQUERY ‘node()’,
path124 =  ‘/a/b/c’ as XQUERY ‘xs:double’ SINGLETON
);

— We get “selective_xml_index_no_compatible_xsd_types” XEvent for /a/b/c
— And XML Reader with XPath Filter, XML Reader, CI Seek on SIDX and CI Scan on base table
SELECT T.id FROM tbl T WHERE T.xmlcol.exist(‘/a/b[c = “43”]’) = 1;

So, to summarize, in this post and the last post we’ve shown:
The SXI cannot be used to search for mixed content.
The ‘AS XQUERY node()’ specification can be used to check for existance of non-terminating node.
The XEvents for SXI can guide you to understanding which nodes to specify.
You must use “As SQL…” hint in order for SXI to be used in XML.value method.
You use “As XQUERY…” hint to use SXI for XQuery predicates or paths in the XML.exist method.

To go back to the BOL examples and test your understanding, write a selective XML index create statement for the following:

SELECT T.record,
T.xmldata.value(‘(/a/b/c/d/e[./f = “SQL”]/g)[1]’, ‘nvarchar(100)’)
FROM myXMLTable T

Cheers, Bob

@bobbeauch