Как оптимизировать время выполнения для преобразования данных в коллекцию? - PullRequest
0 голосов
/ 19 апреля 2011

У меня есть база данных, к которой я должен подключиться через odbc.

Выборка данных занимает приложение. 2 минуты. и полученный DataTable имеет 350000 записей.

Я пытаюсь преобразовать таблицу данных в этот граф объектов. У результирующего набора нет первичного ключа, первичный ключ указывается через представление, из которого я получаю данные.

public class PriceCurve
{
    public PriceCurve(DataTable dt)
    {
        this.Id = int.Parse(dt.AsEnumerable().First()["ID"].ToString());
        this.Prices = new List<Price>();
        GetPrices(dt);
    }

    public int Id { get; private set; }
    public IList<Price> Prices { get; set; }

    private void GetPrices(DataTable dt)
    {
        foreach (DataColumn column in dt.Columns)
        {
            switch (this.GetPriceProviderType(column)) // parses ColumnName to Enum
            {
                case Price.PriceProvider.A:
                    {
                        this.Prices.Add(new Price(Price.PriceProvider.A, dt.AsEnumerable()));
                    }

                    break;
                case Price.PriceProvider.B:
                    {
                        this.Prices.Add(new Price(Price.PriceProvider.B, dt.AsEnumerable()));
                    }

                    break;
            }
        }

    public class Price
    {
        public enum PriceProvider
        {
            A, B
        }

        public Price(PriceProvider type, IEnumerable<DataRow> dt)
        {
            this.Type = type;
            this.TradingDates = new List<TradingDate>();
            this.GetTradingDates(type, dt);
        }

        public IList<TradingDate> TradingDates { get; set; }
        public PriceProvider Type { get; set; }

        private void GetTradingDates(PriceProvider type, IEnumerable<DataRow> dt)
        {
            var data = dt.Select(column => column["TRADING_DATE"]).Distinct();

            foreach (var date in data)
            {
                this.TradingDates.Add(new TradingDate(date.ToString(), type, dt));
            }
        }

        public class TradingDate
        {
            public TradingDate(string id, PriceProvider type, IEnumerable<DataRow> dt)
            {
                this.Id = id;
                this.DeliveryPeriodValues = new Dictionary<int, double?>();
                this.GetDeliveryPeriodValues(type, dt);
            }

            public string Id { get; set; }
            public IDictionary<int, double?> DeliveryPeriodValues { get; set; }

            private void GetDeliveryPeriodValues(PriceProvider type, IEnumerable<DataRow> dt)
            {

                foreach (var row in dt.Where(column => column["TRADING_DATE"].ToString() == this.Name))
                {
                    try
                    {
                        this.DeliveryPeriodValues.Add(
                            int.Parse(row["DELIVERY_PERIOD"].ToString()),
                            double.Parse(row[Enum.GetName(typeof(Price.PriceProvider), type)].ToString()));
                    }
                    catch (FormatException e)
                    {
                        this.DeliveryPeriodValues.Add(
                            int.Parse(row["DELIVERY_PERIOD"].ToString()),
                            null);
                    }
                }    
            }
        }
    }

я создаю один объект, который содержит список из двух объектов. Каждый из этих двух объектов содержит список из 1000 объектов. Каждый из этих 1000 объектов содержит словарь с 350 парами.

Он либо аварийно завершает работу Visual Studio 2010 во время отладки, либо завершается с ошибкой из-за OutOfMemory, либо занимает несколько минут (недопустимо) для выполнения.

Каков наилучший подход к этой проблеме. Я новичок в C # и не знаю, как оптимизировать цикл через эти огромные данные или мой граф объектов. Любая помощь приветствуется.

1 Ответ

1 голос
/ 19 апреля 2011

Это либо приводит к аварийному завершению работы Visual Studio 2010 во время отладки, либо из-за OutOfMemory, либо занимает несколько минут. (недопустимо) выполнить.

Ты заставил меня смеяться. На самом деле.

  • 350.000 узлов - сложная задача на 32-битной машине с .NET. Добавьте немного накладных расходов, и вы мертвы. Используйте объекты, а не таблицу данных, которая ОЧЕНЬ разрушает память.

  • занимает минуты - в значительной степени ваше решение / программирование. Используйте список объектов, а не таблицу данных. Используйте профилировщик. НЕ допускайте ошибок новичка:

var data = dt.Select (column => column ["TRADING_DATE"]). Distinct ();

В этом нет необходимости, позже разберитесь с двойниками в коде. Отдельно дорого. Профилируйте это.

foreach (строка var в dt.Where (column => column ["TRADING_DATE"]. ToString () == this.Name))

Это 350.000 поисков строк по имени, чтобы получить индекс столбца, по сравнению с большим количеством tostring.

Получите профилировщик и узнайте, где именно вы проводите свое время. Избавьтесь, пожалуйста, от таблицы и используйте объекты - DataTable - это нехватка памяти и МЕДЛЕННО по сравнению со списком объектов. И да, это займет несколько минут. Основные причины:

  • Ваше программирование. Не позор. Просто учись, иди к объектам / СЕЙЧАС.
  • ODBC. Требуется время, чтобы просто загрузить данные, тем более что вы не обрабатываете swhile loading (DataReader), но ждете, пока все загрузится, а ODBC НЕ быстрый. 350 000 строк, хорошая сеть, прямой SQL Server - это, возможно, 30 секунд - на той же машине меньше.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...