Selective XML Index’ler: Hiçte Kötü Değil

Selective XML Index’ler: Hiçte Kötü Değil

Hiçbir şekilde bu konuda dünyanın en önde gelen otoritesi değiliz, sadece sorgumuz için en iyi olanı bulana kadar basit bir örnekle oynadık. Böylece hepiniz evinizde oynayabilirsiniz, hepimizin erişebildiği XML’i kullanıyoruz: Sorgu Planları!

Eğer herhangi biriniz sp_BlitzCache kullandıysanız, bir ton XQuery’nin işin içinde olduğunu bilirsiniz. Yakın gelecekte XML indeksleri ekleneceğini bilemiyoruz. Seçici XML Index leri 2012+, bu yüzden 2008R2’nin desteğinin bitmesini beklemek gerekecek. Bu gidişle, SQL Server’ı pencereden atıp sadece arkadaşlarımızın içmesine izin verdiğimiz bir bar açana kadar bu gerçekleşmeyecek.

XML Indexlerinin diğer biçimleri oldukça büyük olabilir ve genellikle varsayılan olarak sınırladığımız nispeten az miktarda XML işleme için oluşturmak için kaynak harcamaya değmez. Performans kazançları orada olmayacaktır.

Peki Seçici XML Indexi nedir? Bu bir Index! XML için! XML’in indekslenecek kısımlarını seçtiğiniz yer. Diğer XML indeksleri ya hep ya hiç şeklindedir ve belgelerinizin boyutuna bağlı olarak oldukça büyük olabilirler. Yanlış hatırlamıyorsak en az veri boyutunda olduklarını düşünüyoruz. Bazı örneklere bir göz atalım.

1

2

3

4

5

6

7

8

SELECT

ID = IDENTITY(INT,1,1),

deq.query_plan

INTO #xml_index_test

FROM sys.dm_exec_cached_plans AS dec

CROSS APPLY sys.dm_exec_query_plan(dec.plan_handle) AS deq

ALTER TABLE #xml_index_test ADD CONSTRAINT pk_id PRIMARY KEY CLUSTERED (ID)

Temp table üzerinde 225 query planı var gözüküyor.

1

2

3

4

5

6

7

8

9

10

11

SET STATISTICS TIME, IO ON

;WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

SELECT xit.ID,

SerialDesiredMemory = xit.query_plan.value(‘sum(//p:MemoryGrantInfo/@SerialDesiredMemory)’, ‘float’) ,

SerialRequiredMemory = xit.query_plan.value(‘sum(//p:MemoryGrantInfo/@SerialRequiredMemory)’, ‘float’),

CachedPlanSize = xit.query_plan.value(‘sum(//p:QueryPlan/@CachedPlanSize)’, ‘float’) ,

CompileTime = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileTime)’, ‘float’) ,

CompileCPU = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileCPU)’, ‘float’) ,

CompileMemory = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileMemory)’, ‘float’)

FROM #xml_index_test AS xit;

Ancak aldığım sorgu planı çok saçma görünüyor ve 1355 sorgu parasına mal oluyor. XML ile çalıştığım için şimdiden pişman olacağız gibi.

I'd rather be querying .jpgs

Deneyebileceğimiz ilk Seçici XML dizini türü, sorguladığımız iki node üzerinde tanımlanır. Bunu şu şekilde oluşturabilirsiniz:

1

2

3

4

5

6

CREATE SELECTIVE XML INDEX ix_xml_selective ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

MemorygrantInfoNode = ‘//p:MemoryGrantInfo’ AS XQUERY ‘node()’,

QueryPlanNode = ‘//p:QueryPlan’ AS XQUERY ‘node()’

);

Sorgumuzu tekrar çalıştırırsak… Hiçbir şey değişmiyor, sadece daha da kötüleşiyor. Tam anlamıyla kötüleşmiyor. Plan ve maliyet aynı, ancak artık işe yaramaz bir dizinimiz var.

1

2

3

4

5

6

7

8

9

10

CREATE SELECTIVE XML INDEX ix_xml_value ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

SerialDesiredMemory = ‘//p:MemoryGrantInfo/@SerialDesiredMemory’ AS SQL INT SINGLETON,

SerialRequiredMemory = ‘//p:MemoryGrantInfo/@SerialRequiredMemory’ AS SQL INT SINGLETON,

CachedPlanSize = ‘//p:QueryPlan/@CachedPlanSize’ AS SQL INT SINGLETON,

CompileTime = ‘//p:QueryPlan/@CompileTime’ AS SQL INT SINGLETON,

CompileCPU = ‘//p:QueryPlan/@CompileCPU’ AS SQL INT SINGLETON,

CompileMemory = ‘//p:QueryPlan/@CompileMemory’ AS SQL INT SINGLETON

);

Bu da hiçbir fark yaratmıyor. Her yolu döndürdüğümüz SQL türü olarak tanımlamayı denedik. Yine aynı plan, aynı maliyet. Sırada ne var?

1

2

3

4

5

6

7

8

9

10

CREATE SELECTIVE XML INDEX ix_xml_selective ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

SerialDesiredMemory = ‘//p:MemoryGrantInfo/@SerialDesiredMemory’ AS XQUERY ‘xs:double’ SINGLETON,

SerialRequiredMemory = ‘//p:MemoryGrantInfo/@SerialRequiredMemory’ AS XQUERY ‘xs:double’ SINGLETON,

CachedPlanSize = ‘//p:QueryPlan/@CachedPlanSize’ AS XQUERY ‘xs:double’ SINGLETON,

CompileTime = ‘//p:QueryPlan/@CompileTime’ AS XQUERY ‘xs:double’ SINGLETON,

CompileCPU = ‘//p:QueryPlan/@CompileCPU’ AS XQUERY ‘xs:double’ SINGLETON,

CompileMemory = ‘//p:QueryPlan/@CompileMemory’ AS XQUERY ‘xs:double’ SINGLETON

);

Son olarak, her bir yolu veri türüyle birlikte onları almak için kullandığımız XQuery ifadesi olarak tanımlamayı denedik. Bu nihayet bir fark yarattı, hem de çok büyük bir fark. Sorgu maliyeti 0,55’e düştü. Bir dizin için hiç de fena değil.

What time is it, even?

Sadece XML Seçme

.exist(), .nodes() veya .query() gibi diğer olası XQuery yöntemlerine ya da herhangi bir yerdeki verileri birleştirmek için sql:column kullanımına girmiyorumuz. Bu, bir blog yazısında uğraşmak istediğimden daha fazla XML demek. XML’i çok kullanıyorsanız ve SQL Server 2012+ kullanıyorsanız, SXI’lere bir şans vermek isteyebilirsiniz. Çalışmalarını sağladığınızda oldukça havalı olabilirler.