Как улучшить производительность DataSet.ReadXml, если я использую схему? - PullRequest
1 голос
/ 21 ноября 2008

У меня есть набор данных ADO, который я загружаю из его XML-файла через ReadXml. Данные и схема находятся в отдельных файлах.

В данный момент загрузка этого набора данных занимает около 13 секунд. Я могу сократить это до 700 миллисекунд, если я не читаю схему DataSet и просто позволяю ReadXml выводить схему, но тогда результирующий DataSet не содержит никаких ограничений.

Я пытался сделать это:

Console.WriteLine("Reading dataset with external schema.");
ds.ReadXmlSchema(xsdPath);
Console.WriteLine("Reading the schema took {0} milliseconds.", sw.ElapsedMilliseconds);
foreach (DataTable dt in ds.Tables)
{
   dt.BeginLoadData();
}
ds.ReadXml(xmlPath);
Console.WriteLine("ReadXml completed after {0} milliseconds.", sw.ElapsedMilliseconds);
foreach (DataTable dt in ds.Tables)
{
   dt.EndLoadData();
}
Console.WriteLine("Process complete at {0} milliseconds.", sw.ElapsedMilliseconds);

Когда я делаю это, чтение схемы занимает 27 мс, а чтение DataSet занимает 12000+ миллисекунд. И это время, сообщенное до . Я вызываю EndLoadData для всех таблиц данных.

Это не огромный объем данных - он составляет около 1,5 МБ, нет вложенных отношений, и все таблицы содержат два или три столбца из 6-30 символов. Единственное, что я могу понять, это другое, если я прочитал схему заранее, это то, что схема включает в себя все уникальные ограничения. Но BeginLoadData должен отключать ограничения (а также уведомления об изменениях и т. Д.). Так что это не должно применяться здесь. (И да, я попытался просто установить EnforceConstraints в false.)

Я читал много сообщений о людях, улучшающих время загрузки DataSets, сначала читая схему, а не заставляя объект выводить схему. В моем случае вывод схемы делает процесс примерно в 20 раз быстрее, чем схема, предоставленная явно.

Это сводит меня с ума. Схема этого DataSet генерируется на основе метаинформации, и у меня возникает соблазн написать метод, который создает его программно и просто десерализует его с помощью XmlReader. Но я бы предпочел не делать этого.

Чего мне не хватает? Что еще я могу сделать, чтобы улучшить скорость здесь?

Ответы [ 3 ]

1 голос
/ 02 июня 2012

Я постараюсь дать вам сравнение производительности между хранением данных в текстовых и XML-файлах.

Первая функция создает два файла: один файл с 1000000 записями в виде простого текста и один файл с 1000000 (одинаковыми данными) записями в формате xml. Сначала вы должны заметить разницу в размере файла: ~ 64 МБ (обычный текст) против ~ 102 МБ (файл xml).

void create_files()
    {
        //create text file with data
        StreamWriter sr = new StreamWriter("plain_text.txt");

        for(int i=0;i<1000000;i++)
        {
            sr.WriteLine(i.ToString() + "<SEP>" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb" + i.ToString());
        }

        sr.Flush();
        sr.Close();

        //create xml file with data
        DataSet ds = new DataSet("DS1");

        DataTable dt = new DataTable("T1");

        DataColumn c1 = new DataColumn("c1", typeof(int));
        DataColumn c2 = new DataColumn("c2", typeof(string));

        dt.Columns.Add(c1);
        dt.Columns.Add(c2);

        ds.Tables.Add(dt);

        DataRow dr;

        for(int j=0; j< 1000000; j++)
        {
            dr = dt.NewRow();
            dr[0]=j;
            dr[1] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb" + j.ToString();
            dt.Rows.Add(dr);
        }

        ds.WriteXml("xml_text.xml");

    }

Вторая функция читает эти два файла: сначала она читает простой текст в словарь (просто для имитации реального использования), а затем читает файл XML. Оба шага измеряются в миллисекундах (и результаты записываются на консоль):

Начало чтения текстового файла в память
Текстовый файл загружен в память за 7628 миллисекунд
Начать чтение XML-файла в память
Файл XML загружен в память за 21018 миллисекунд

void read_files()
    {

        //timers
        Stopwatch stw = new Stopwatch();
        long milliseconds;

        //read text file in a dictionary

        Debug.WriteLine("Start read Text file into memory");

        stw.Start();
        milliseconds = 0;

        StreamReader sr = new StreamReader("plain_text.txt");
        Dictionary<int, string> dict = new Dictionary<int, string>(1000000);
        string line;
        string[] sep = new string[]{"<SEP>"};
        string [] arValues;
        while (sr.EndOfStream!=true) 
        {
            line = sr.ReadLine();
            arValues = line.Split(sep,StringSplitOptions.None);
            dict.Add(Convert.ToInt32(arValues[0]),arValues[1]);
        }

        stw.Stop();
        milliseconds = stw.ElapsedMilliseconds;

        Debug.WriteLine("Text file loaded into memory in " + milliseconds.ToString() + " milliseconds" );



        //create xml structure
        DataSet ds = new DataSet("DS1");

        DataTable dt = new DataTable("T1");

        DataColumn c1 = new DataColumn("c1", typeof(int));
        DataColumn c2 = new DataColumn("c2", typeof(string));

        dt.Columns.Add(c1);
        dt.Columns.Add(c2);

        ds.Tables.Add(dt);

        //read xml file

        Debug.WriteLine("Start read XML file into memory");

        stw.Restart();
        milliseconds = 0;

        ds.ReadXml("xml_text.xml");

        stw.Stop();
        milliseconds = stw.ElapsedMilliseconds;

        Debug.WriteLine("XML file loaded into memory in " + milliseconds.ToString() + " milliseconds");

    }

Вывод: размер файла XML почти в два раза больше размера текстового файла и загружается в три раза медленнее, чем текстовый файл.

Обработка XML более удобна (из-за уровня абстракции), чем простой текст, но требует больше ресурсов процессора / диска.

Итак, если у вас небольшие файлы и это приемлемо с точки зрения производительности, наборы данных XML более чем нормальны. Но если вам нужна производительность, я не знаю, быстрее ли набор данных XML (с любым доступным методом), чем обычные текстовые файлы. И в основном, это начинается с самой первой причины: XML-файл больше, потому что в нем больше тегов.

0 голосов
/ 25 февраля 2009

Другой вариант измерения - прочитать набор данных без схемы, а затем объединить в типизированный набор данных с включенными ограничениями. Таким образом, у него есть все данные под рукой, поскольку он строит индексы, используемые для обеспечения ограничений - может быть, это будет более эффективным?

С MSDN :

Метод Merge обычно называется в конце серии процедур которые включают проверку изменений, исправление ошибок, обновление данных источник с изменениями и, наконец, обновление существующего DataSet

.

0 голосов
/ 03 декабря 2008

Это точно не ответ (хотя это лучше, чем ничего, что я и получил до сих пор), но после долгого времени борьбы с этой проблемой я обнаружил, что он полностью отсутствует, когда моя программа не работает внутри Visual Studio ,

Что-то, о чем я раньше не упоминал, что делает это еще более загадочным, это то, что когда я загружал другой (но сравнительно большой) XML-документ в DataSet, программа работала очень хорошо. Теперь мне интересно, если к одному из моих наборов данных прикреплена какая-то метаинформация, которую Visual Studio проверяет во время выполнения, а другой - нет. Я не знаю.

...