설정:
create table dbo.T
(
ID int identity primary key,
XMLDoc xml not null
);
insert into dbo.T(XMLDoc)
select (
select N.Number
for xml path(''), type
)
from (
select top(10000) row_number() over(order by (select null)) as Number
from sys.columns as c1, sys.columns as c2
) as N;
각 행의 샘플 XML :
<Number>314</Number>
쿼리의 작업 T
은 지정된 값을 가진 행 수를 계산하는 것 입니다 <Number>
.
이를 수행하는 두 가지 확실한 방법이 있습니다.
select count(*)
from dbo.T as T
where T.XMLDoc.value('/Number[1]', 'int') = 314;
select count(*)
from dbo.T as T
where T.XMLDoc.exist('/Number[. eq 314]') = 1;
그것은이 밝혀 value()
과 exists()
작업에 선택적 XML 인덱스에 대한 두 개의 서로 다른 경로 정의를 필요로한다.
create selective xml index SIX_T on dbo.T(XMLDoc) for
(
pathSQL = '/Number' as sql int singleton,
pathXQUERY = '/Number' as xquery 'xs:double' singleton
);
sql
버전입니다 value()
및 xquery
버전입니다 exist()
.
이와 같은 색인을 사용하면 탐색이 잘되는 계획을 제공 할 수 있지만 선택적 XML 색인은 기본 키가 T
시스템 테이블의 클러스터 키의 리드 키인 시스템 테이블로 구현됩니다 . 지정된 경로는 해당 테이블의 스파 스 열입니다. 정의 된 경로의 실제 값에 대한 색인을 원할 경우 각 경로 표현식마다 하나씩 보조 선택 색인을 작성해야합니다.
create xml index SIX_T_pathSQL on dbo.T(XMLDoc)
using xml index SIX_T for (pathSQL);
create xml index SIX_T_pathXQUERY on dbo.T(XMLDoc)
using xml index SIX_T for (pathXQUERY);
에 대한 쿼리 계획 exist()
은 선택적인 XML 인덱스에 대한 시스템 테이블에서 키 조회 (2 차 XML 인덱스에서 검색)를 수행하고 (필요한 이유를 모름) 최종적으로 T
실제로 있는지 확인하기 위해 검색을 수행 합니다. 거기에 행. 시스템 테이블과 사이에 외래 키 제약 조건이 없으므로 마지막 부분이 필요합니다 T
.
value()
쿼리 계획 이 그리 좋지 않습니다. T
내부 테이블에서 찾기에 대해 중첩 루프 조인 으로 클러스터 된 인덱스 스캔을 수행 하여 스파 스 열에서 값을 가져오고 마지막으로 값을 필터링합니다.
선택적 인덱스의 사용 여부는 최적화 전에 결정되지만 2 차 선택적 인덱스의 사용 여부는 옵티마이 저의 비용 기반 결정입니다.
where 절이 필터링 될 때 2 차 선택적 색인이 사용되지 않는 이유는 무엇 value()
입니까?
최신 정보:
쿼리는 의미 적으로 다릅니다. 값이있는 행을 추가하면
<Number>313</Number>
<Number>314</Number>`
exist()
버전은 2 개 행을 계산 것와 values()
쿼리가 1 개 행을 계산한다. 그러나 singleton
지시문을 사용하여 여기에 지정된 인덱스 정의를 사용하면 SQL Server에서 여러 <Number>
요소가 있는 행을 추가 할 수 없습니다 .
그러나 컴파일러가 단일 값만 얻도록 보장하기 위해 values()
지정하지 않고 함수를 사용할 수는 없습니다 [1]
. 이것이 [1]
우리가 value()
계획 에서 Top N Sort를 갖는 이유 입니다.
내가 대답을 마치고있는 것 같습니다 ...