Большие проблемы с производительностью при использовании Oracle DataReader в .Net

У меня есть несколько процедур Oracle, которые генерируют/возвращают большой объем данных, которые мне нужно записать в файл. В настоящее время я пытаюсь выполнить с помощью считывателя данных. Кажется, это работает, я успешно сгенерировал файл размером 479 МБ без каких-либо проблем. С момента получения dataReader до завершения файла прошло менее 4 минут.

Но dataReader, который я получаю для конкретной процедуры, сканирует. Это невероятно медленно. Я изменил свой код, чтобы попытаться лучше понять, что происходит....

System.Diagnostics.Debug.Write("Performing .Read() on DataReader: ")
Dim d1 As DateTime = DateTime.Now
Dim result As Boolean = myDataReader.Read()
Dim ts As TimeSpan = DateTime.Now.Subtract(d1)
System.Diagnostics.Debug.WriteLine(ts.ToString)

Интересно то, что мой вывод в конечном итоге выглядит так:

Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:00:00
Performing .Read() on DataReader: 00:07:33.5037500

Я действительно в недоумении, что делать дальше. Я не вижу ничего уникального или необычного в строке, занимающей 07:33.5037500. Какие-либо предложения?

ИЗМЕНИТЬ:

Спасибо за ответы всем. Во-первых, насколько я могу судить, никаких исключений не выбрасывается. Как было предложено, я взглянул на эту конкретную процедуру, которая демонстрирует поведение, описанное выше, и хотя процедура смехотворно массивна; но похоже, что он использует много курсоров для заполнения временной таблицы оракула. Возвращаемый Ref Cursor — это SELECT * FROM этой временной таблицы.

Я пишу блок PL/SQL, который откроет этот курсор, чтобы увидеть, существует ли проблема с производительностью, когда я удаляю код .Net... надеюсь, это поможет; но если у вас есть какие-либо дополнительные мысли, это будет очень признательно.

Еще раз спасибо. Похоже, это проблема PL/SQL, а не проблема .NET.


person Rob P.    schedule 10.11.2010    source источник
comment
недостаточно информации, чтобы ответить банкомату ... за исключением того, что он генерирует исключения, которые обрабатываются молча?   -  person Mitch Wheat    schedule 10.11.2010
comment
вам, вероятно, следует опубликовать больше вашего полного кода...   -  person Mitch Wheat    schedule 10.11.2010


Ответы (3)


Что на самом деле делает база данных?

Запросу с GROUP BY или и ORDER BY может потребоваться сгенерировать полный набор результатов, а затем отсортировать/объединить его перед возвратом строки. Запрос, сканирующий большую таблицу, может найти 50 строк в первых нескольких блоках, а затем прочитать еще сто тысяч блоков, прежде чем найдет еще один.

Я предлагаю вам игнорировать код VB и опубликовать код базы данных.

person Gary Myers    schedule 10.11.2010
comment
Процедура смехотворно массовая; но похоже, что он использует много курсоров для заполнения временной таблицы Oracle. Возвращаемый Ref Cursor — это SELECT * FROM этой временной таблицы. - person Rob P.; 10.11.2010
comment
Тогда я думаю, вы можете в значительной степени гарантировать, что проблема где-то в коде PL/SQL и запросах. Попросите вашего администратора базы данных помочь вам разобраться в деталях. - person Gary Myers; 10.11.2010

Я предполагаю, что когда вы говорите «конкретная процедура», вы имеете в виду, что вы вызываете хранимую процедуру Oracle с параметром OUT, который является REF CURSOR. Затем ваш DataReader извлекает данные из курсора, возвращенного процедурой. Так ли это?

Если да, то можете ли вы исключить код .Net и написать блок PL/SQL, который вызывает процедуру и извлекает все данные из курсора, чтобы увидеть, получится ли у вас такое же поведение? Oracle не материализует данные при открытии курсора — он материализует результаты, когда клиент извлекает данные. Так что вполне возможно, что Oracle придется проделать довольно много работы, чтобы получить N-ю строку, если ему нужно материализовать и отфильтровать кучу данных, прежде чем он найдет N+1-ю строку. Если вы видите такое же поведение в PL/SQL, работающем с базой данных, почти наверняка дело именно в этом. Если вы не видите никаких проблем в блоке PL/SQL, значит, что-то происходит на среднем уровне.

person Justin Cave    schedule 10.11.2010
comment
Спасибо - да, это параметр OUT, который является REF CURSOR. Попробую на PL/SQL и сравню. - person Rob P.; 10.11.2010

Всего несколько общих комментариев к исходной версии вашего вопроса:

Если вы используете встроенный в Microsoft .NET Framework System.Data. классов поставщиков OracleClient, вы можете повысить производительность с помощью Собственный обновленный поставщик .NET от Oracle.

Если время смещается при каждом запуске, возможно, сборщик мусора .NET вмешивается в использование памяти, чего нет в вашем примере (т. е. если создается и выбрасывается множество объектов).

person John K    schedule 10.11.2010