У меня 16 больших XML-файлов. Когда я говорю «Большой», я говорю в гигабайтах. Один из этих файлов более 8 ГБ. Некоторые из них более 1 ГБ. Они даны мне от внешнего поставщика.
Я пытаюсь импортировать XML в базу данных, чтобы разбить его на таблицы. В настоящее время я передаю 10000 записей за раз из файла в память и вставляю большой двоичный объект. Я использую SSIS с задачей сценария, чтобы сделать это. На самом деле это ОЧЕНЬ быстро для всех файлов, кроме файла 8 ГБ.
Я не могу загрузить весь файл в XML-документ. Я не могу подчеркнуть это достаточно. Это была итерация 1, и файлы настолько огромны, что система просто зависает, пытаясь обработать эти файлы, в частности, 8-гигабайтный.
Я запустил свой текущий «разделитель файлов», и он потратил 7 часов на импорт данных XML, но все еще не закончил. Он импортировал 363 блока по 10000 записей из файла размером 8 ГБ, но все еще не был готов.
К вашему сведению, вот как я сейчас передаю свои файлы в память (10 000 записей за раз). Я нашел код на 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();
}
}
Таким образом, он отлично работает на всех файлах, кроме 8 ГБ, где при дальнейшей и дальнейшей потоковой передаче в файл требуется больше и больше времени.
Я хотел бы разбить файл на более мелкие куски, но сплиттер должен быть быстрым. Тогда стример и остальная часть процесса могут работать быстрее. Каков наилучший способ разделения файлов? В идеале я бы сам разбил его на код в SSIS.
EDIT:
Вот код, который фактически выводит мои данные с использованием методологии потоковой передачи.
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);
}
}