2010-10-20 4 views
12

Sto cercando di inserire alcuni dati da un documento XML in una tabella delle variabili. Quello che mi fa venire in mente è che le stesse operazioni di selezione (alla rinfusa) in pochissimo tempo, mentre insert-select impiega anni e mantiene il processo di SQL Server responsabile per l'utilizzo della CPU al 100% mentre la query viene eseguita.Perché inserire - selezionare la tabella delle variabili dalla variabile XML in modo lento?

Ho dato un'occhiata al piano di esecuzione e INDEED c'è una differenza. Insert-select aggiunge un nodo extra "Table spool" anche se non assegna alcun costo. La "Funzione con valori di tabella [Lettore XML]" ottiene il 92%. Con select-in, i due "Funzione di tabella [Lettore XML]" ricevono il 49% ciascuno.

Spiegare "PERCHÉ sta succedendo" e "COME risolvere questo (elegantemente)" come posso effettivamente inserire in una tabella temporanea e quindi a sua volta inserire nella tabella delle variabili, ma è solo raccapricciante.

Ho provato questo su SQL 10.50.1600, 10.00.2531 con gli stessi risultati

Ecco un banco di prova:

declare @xColumns xml 
declare @columns table(name nvarchar(300)) 

if OBJECT_ID('tempdb.dbo.#columns') is not null drop table #columns 

insert @columns select name from sys.all_columns 

set @xColumns = (select name from @columns for xml path('columns')) 

delete @columns 

print 'XML data size: ' + cast(datalength(@xColumns) as varchar(30)) 

--raiserror('selecting', 10, 1) with nowait 

--select ColumnNames.value('.', 'nvarchar(300)') name 
--from @xColumns.nodes('/columns/name') T1(ColumnNames) 

raiserror('selecting into #columns', 10, 1) with nowait 

select ColumnNames.value('.', 'nvarchar(300)') name 
into #columns 
from @xColumns.nodes('/columns/name') T1(ColumnNames) 

raiserror('inserting @columns', 10, 1) with nowait 

insert @columns 
select ColumnNames.value('.', 'nvarchar(300)') name 
from @xColumns.nodes('/columns/name') T1(ColumnNames) 

ringrazia un mazzo !!

risposta

19

Questo è un bug in SQL Server 2008. Usa

insert @columns 
select ColumnNames.value('.', 'nvarchar(300)') name 
from @xColumns.nodes('/columns/name') T1(ColumnNames) 
OPTION (OPTIMIZE FOR (@xColumns = NULL)) 

Questa soluzione alternativa proviene da un articolo su Microsoft Connect Site che menziona anche una correzione per questo problema di lettore di spool/XML Eager disponibile (in traceflag 4130).

La ragione per la regressione prestazioni è spiegato in a different connect item

Il rocchetto è stato introdotto a causa di una logica di protezione generale halloween (che non è necessario per le espressioni XQuery).

+0

Ha funzionato come un incantesimo, grazie! Spiegazione precisa ... MS divertente – Rbjz

6

Sembra essere un problema specifico per SQL Server 2008. Quando eseguo il codice in SQL Server 2005, entrambi gli inserti vengono eseguiti rapidamente e producono piani di esecuzione identici che iniziano con il frammento mostrato di seguito come Piano 1. Nel 2008, il primo inserto utilizza Piano 1 ma il secondo inserto produce Piano 2. Il resto di entrambi i piani oltre il frammento mostrato è identico.

Piano 1

alt text

Piano 2

alt text

+0

Esattamente :) grazie. Però, la risposta di Martin uccide il bug per me. Ora cosa faccio della tua risposta? Vota, accetta pure? Saluti, Rob – Rbjz

Problemi correlati