Tengo 16 archivos xml grandes. Cuando digo Large, estoy hablando en gigabytes. Uno de estos archivos tiene más de 8 GB. Varios de ellos tienen más de 1 gb. Estos me son proporcionados por un proveedor externo.Problemas con los GRANDES archivos XML
Estoy tratando de importar el XML en una base de datos para poder triturarlo en tablas. Actualmente, transfiero 10.000 registros a la vez fuera del archivo a la memoria e inserto el blob. Yo uso SSIS con una tarea de script para hacer esto. Esto es realmente MUY rápido para todos los archivos, excepto el archivo de 8 GB.
No puedo cargar todo el archivo en un documento xml. No puedo enfatizar esto lo suficiente. Esa fue la iteración 1 y los archivos son tan grandes que el sistema simplemente se bloquea intentando tratar con estos archivos, el de 8 gb en particular.
Corrí mi actual "divisor de archivos" y pasó 7 horas en la importación de los datos xml y todavía no estaba hecho. Importó 363 bloques de 10.000 registros del archivo de 8 GB y todavía no estaba hecho.
FYI, así es como actualmente estoy transmitiendo mis archivos en la memoria (10,000 registros a la vez). He encontrado el código en http://blogs.msdn.com/b/xmlteam/archive/2007/03/24/streaming-with-linq-to-xml-part-2.aspx
private static IEnumerable<XElement> SimpleStreamAxis(string fileName, string matchName)
{
using (FileStream stream = File.OpenRead(fileName))
{
using (XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings() { ProhibitDtd = false }))
{
reader.MoveToContent();
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == matchName)
{
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
break;
}
}
reader.Close();
}
stream.Close();
}
}
Por lo tanto, funciona bien en todos los archivos, excepto los 8 GB aquel en el que se tiene que transmitir más y más en el archivo que se necesita más tiempo y más tiempo.
Lo que me gustaría hacer es dividir el archivo en trozos más pequeños, pero el separador debe ser rápido. Luego, el transmisor y el resto del proceso pueden ejecutarse más rápidamente. ¿Cuál es la mejor forma de dividir los archivos? Idealmente, me dividiría en código en SSIS.
EDIT:
Aquí está el código que realmente páginas fuera mis datos utilizando la metodología de streaming.
connection = (SqlConnection)cm.AcquireConnection(null);
int maximumCount = Convert.ToInt32(Dts.Variables["MaximumProductsPerFile"].Value);
int minMBSize = Convert.ToInt32(Dts.Variables["MinimumMBSize"].Value);
int maxMBSize = Convert.ToInt32(Dts.Variables["MaximumMBSize"].Value);
string fileName = Dts.Variables["XmlFileName"].Value.ToString();
FileInfo info = new FileInfo(fileName);
long fileMBSize = info.Length/1048576; //1024 * 1024 bytes in a MB
if (minMBSize <= fileMBSize && maxMBSize >= fileMBSize)
{
int pageSize = 10000; //do 2000 products at one time
if (maximumCount != 0)
pageSize = maximumCount;
var page = (from p in SimpleStreamAxis(fileName, "product") select p).Take(pageSize);
int current = 0;
while (page.Count() > 0)
{
XElement xml = new XElement("catalog",
from p in page
select p);
SubmitXml(connection, fileName, xml.ToString());
//if the maximum count is set, only load the maximum (in one page)
if (maximumCount != 0)
break;
current++;
page = (from p in SimpleStreamAxis(fileName, "product") select p).Skip(current * pageSize).Take(pageSize);
}
}
Los documentos XmlReader dicen que para los archivos grandes que "requieren una cantidad sustancial de tiempo para su procesamiento", debe "crear una implementación IStream personalizada". ¿Has probado eso? – Ken
"Actualmente, reproduzco 10.000 registros a la vez del archivo en la memoria e inserto el blob" - ¿de verdad está usando un BLOB? No entiendo exactamente lo que intenta hacer aquí porque MS SQL Server puede trabajar de forma nativa con XML. – Hut8
Elimina las llamadas '.Close()'. La declaración 'using' se encarga de eso en estas dos instancias particulares. –