Kurmak:
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;
Her satır için örnek XML:
<Number>314</Number>
Sorgunun işi, T
belirtilen değeri olan satır sayısını saymaktır <Number>
.
Bunu yapmanın iki belirgin yolu vardır:
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;
Bu ortaya çıkıyor value()
ve exists()
seçici XML dizininin çalışması için iki farklı yol tanımı gerektiriyor.
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
Versiyon içindir value()
ve xquery
versiyon içindir exist()
.
Bunun gibi bir dizinin size güzel bir arama içeren bir plan vereceğini düşünebilirsiniz, ancak seçici XML dizinleri, sistem tablosunun T
kümelenmiş anahtarının ana anahtarı olarak birincil anahtarla bir sistem tablosu olarak uygulandığını düşünebilirsiniz . Belirtilen yollar, o tablodaki seyrek sütunlardır. Tanımlı yolların gerçek değerlerinin bir dizinini istiyorsanız, her yol ifadesi için bir tane olmak üzere ikincil seçici dizinler oluşturmanız gerekir.
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);
Sorgu planı exist()
ikincil XML dizininde bir arama yapar ve ardından seçici XML dizini için sistem tablosunda bir anahtar araması yapar (neden gerekli olduğunu bilmiyorum) ve son olarak T
gerçekten olduğundan emin olmak için bir arama yapar orada satırlar. Son bölüm gereklidir, çünkü sistem tablosu ve arasında yabancı anahtar kısıtlaması yoktur T
.
value()
Sorgu planı çok hoş değil. T
İçerideki döngüler kümelenmiş bir dizin taraması yapar, iç tablodaki bir aramaya karşı seyrek sütundan değeri alır ve son olarak değeri filtreler.
Optimizasyondan önce bir seçici endeksin kullanılması gerekip gerekmediğine karar verilirse, ancak ikincil bir seçici endeksin kullanılması gerekip gerekmediği, optimizatör tarafından maliyete dayalı bir karardır.
Where yan tümcesi filtrelendiğinde neden ikincil seçici dizin kullanılmıyor value()
?
Güncelleme:
Sorgular anlamsal olarak farklıdır. Değerli bir satır eklerseniz
<Number>313</Number>
<Number>314</Number>`
exist()
sürüm 2 satır sayılır ve values()
sorgu 1 satır sayılır. Ancak burada belirtildiği gibi dizin tanımları ile singleton
SQL Server yönergesini kullanarak birden çok <Number>
öğeye sahip bir satır eklemenizi engeller .
Ancak bu , derleyiciye yalnızca tek bir değer alacağımızı garanti etmek için values()
belirtmeden işlevi kullanmamıza izin vermez [1]
. Yani [1]
biz sırala Top N olması nedeni value()
planı.
Görünüşe göre burada bir cevaba yaklaşıyorum ...