2012-07-15 26 views
5

Estoy trabajando con el XML de observación actual de NOAA (ejemplo: Washington DC) y estoy triturando los archivos de las 4000+ estaciones en una tabla de SQL Server 2008 R2. Después de probar muchos enfoques diferentes, tengo uno con el que estoy avanzando.SQL Server XML shredding performance

Esta pregunta es sobre el rendimiento entre los diferentes métodos y lo más importante es por qué es tan drástico.

primer intento

Trabajando en C# Me analizado sintácticamente todos los archivos con LINQ to XML y escribió los registros resultantes de la base de datos con LINQ a SQL. El código para esto es predecible, así que no te aburriré con eso.

Reescribir con linq a Entity Framework no ayudó.

Esto dio como resultado que la aplicación tardara más de una hora en ejecutarse y solo había procesado unos 1600 archivos. La lentitud es el resultado tanto de Linq a SQL como de Linq a entidades que ejecutan una inserción y seleccionan para cada registro.

segundo intento

Todavía trabajando en C# Me trataron de acelerarlo mediante el uso de los métodos de inserción a granel disponible en línea (ejemplo: Speeding up inserts using Linq-to-SQL - Part 1).

Todavía lento, aunque notoriamente más rápido que el primer intento.

En este punto pasé a utilizar un procedimiento almacenado para manejar la trituración XML e insertar con el código C# concatenando los archivos en una cadena XML y agregando una etiqueta contenedora.

tercer intento

El uso de XML Query de SQL Server similar a este (@xml es el archivo XML) [de la memoria]:

select credit = T.observation.value('credit[1]', 'varchar(256)') 
     ,... -- the rest of the elements possible in the file. 
from @xml.nodes('wrapper') W(station) 
    cross apply W.station.nodes('current_observation') T(observation) 

que se deja correr durante 15 minutos y se cancela con 250 o más registros procesados.

cuarto intento

me cambió la consulta para utilizar OpenXML:

declare $idoc int 

exec sp_xml_preparedocument @idoc output, @xml 

select Credit 
     ,... -- the rest of the elements 
from openxml(@idoc, '/wrapper/current_observations', 2) 
    with (
     Credit varchar(256) 'credit' 
     ,...) -- the rest of the elements 

exec sp_xml_removedocument @idoc 

Este procesados ​​todos los registros de 4000 en 10 segundos! Muy aceptable.

Mientras esperaba algunas diferencias entre los métodos, no esperaba que la diferencia fuera tan dramática.

Así que mi pregunta es, simplemente,

'¿Por qué hay una diferencia tan drástica en el rendimiento entre los diferentes métodos?

Estoy muy contento de que se muestre que estaba usando las 3 primeras incorrectas.

Respuesta

2

Una cosa que podría poder hacer para acelerar la opción de XQuery es evitar la unión cruzada.

no puedo ver lo que parece el código XML como - que muestra Washington DC sólo contiene un único nodo - pero asumiendo el XML sólo contiene un <wrapper> y luego una lista de <current_observation> dentro de esa, entonces se podría optimizar su XQuery para leer :

select 
    credit = T.observation.value('credit[1]', 'varchar(256)') 
    ,... -- the rest of the elements possible in the file. 
from 
    @xml.nodes('wrapper/current_observation') T(observation) 

y eso debería funcionar mucho más rápido que la velocidad que ha visto en sus pruebas.

Si tiene tiempo para probar esto, me interesaría saber cómo se apila este enfoque modificado, contra su Xquery original y contra la solución OPENXML.

+0

sí, estoy sacando el nodo current_observation de cada archivo y concatenándolos con un elemento alrededor del lote de ellos. –

+1

Pensé que había intentado hacer referencia a la etiqueta current_observation sin aplicar la cruz, pero aparentemente no. Vuelvo a ejecutar la prueba con los cambios sugeridos y, como esperabas, los tiempos son mucho más rápidos. Para procesar los más de 4000 elementos current_observation tomó 43 segundos. Si bien tomó 4 veces más tiempo, está en el mismo vecindario y explica por qué las diferencias fueron tan drásticas antes. –

+0

@DavidCulp: genial, gracias por los comentarios! Es bueno saber –

1

¿Puede confirmar que no está utilizando el eje principal ('..') en su consulta? Esto puede destruir el rendimiento. También puede agregar el acceso de texto() que también debería mejorar el rendimiento de la siguiente manera:

select 
o.c.value('(credit/text())[1]', 'varchar(max)'), 
--... 
from @xml.nodes('wrapper/current_observation') o(c) 
+0

No estoy usando el eje padre. –

0

¿Probó el acceso de texto? Obtuve una mejora del 15-20% en mi reproción frente a un archivo xml de 6MB con 4.096 registros, aunque esto solo se aplica a XML sin tipo (sin XSD asociado en SQL Server).

También encontré que mi consulta se ejecuta en 10-12 segundos, por lo que todavía estoy un poco desconcertado por sus 43 segundos. ¿Qué versión/service pack de SQL Server está usando? Recuerdo que solía haber un problema en SQL 2005 cuando insertaba en una variable de tabla, pero pensé que esto se había solucionado.

Cuestiones relacionadas