Проблемы с производительностью хранимых процедур ODP.Net для больших наборов данных

У нас возникли серьезные проблемы с производительностью при выполнении запросов SELECT из одной из наших баз данных. См. простую процедуру и соответствующий код ниже.

В коде метод ExecuteReader() выполняется примерно за 10 секунд для запроса, возвращающего 30 тысяч записей. Итерация Reader занимает 2 минуты (даже если я не перекачиваю данные ни в какой другой объект). 2 минуты для набора данных из 30 тыс. строк для нас неприемлемы, поскольку мы ожидаем, что наборы данных будут исчисляться миллионами.

Есть ли здесь что-то, что выделяется для кого-либо из вас? Надеюсь, что ваш опыт работы с ODP.NET и PL/SQL может помочь.

    create or replace PROCEDURE              TRACKING_FETCH (
                p_tracking_id             IN NUMBER,
                p_parent_id               IN NUMBER,
                p_media_id                IN NUMBER,
                p_custodian_id            IN NUMBER,
                p_return_cursor           OUT SYS_REFCURSOR)
AS
BEGIN
     OPEN p_return_cursor FOR
            SELECT 
                  * 
            FROM
                  tracking
            WHERE
                  (tracking_id = p_tracking_id OR p_tracking_id = 0)
            AND   (parent_id = p_parent_id OR p_parent_id = 0) 
            AND   (media_id = p_media_id OR p_media_id = 0)
            AND  (custodian_id = p_custodian_id OR p_custodian_id = 0);
END TRACKING_FETCH;

--

using (DataFactory command 
       = new DataFactory(dbConnection, 
                         DatabaseType.Oracle, 
                         CommandType.StoredProcedure, 
                         "TRACKING_FETCH"))
{
       command.AddInParameter("p_tracking_id", DbType.Int32, trackingid);
       command.AddInParameter("p_parent_id", DbType.Int32, parentid);
       command.AddInParameter("p_media_id", DbType.Int32, mediaid);
       command.AddInParameter("p_custodian_id", DbType.Int32, custodianid);
       using (var dr = command.ExecuteReader())
       {
              while (dr.Read())
              {
                  //Do Things...
              }
       }
}

Любое руководство будет принято с благодарностью.


person mattdlong    schedule 08.12.2009    source источник


Ответы (3)


Стоит изучить интерфейс ожидания Oracle. Я подозреваю, что сетевая задержка убивает вас. Процедура возвращает указатель на результирующий набор. Я бы предположил, что в какой-то момент вашего цикла вы извлекаете строки (даже если они сбрасываются).

Проверка v$sql покажет вам, сколько выборок выполняется и сколько строк обрабатывается. Разделите одно на другое, и вы увидите, сколько строк за выборку. Если вы делаете 1 строку/выборку или даже 10-20, это тысячи сетевых ожиданий. В идеале вам нужны тысячи строк на выборку, если вы собираетесь извлекать миллионы записей, хотя это может стоить вам памяти.

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

person Gary Myers    schedule 09.12.2009
comment
Да, вы были правы насчет задержки, убивающей нас, я не понимал, что каждое чтение считывателя данных было круговым путешествием. Мы решили эту проблему, установив поле «FetchSize» в OracleDataReader, которое сообщает читателю, сколько данных нужно возвращать с каждым круговым циклом. Спасибо за вашу помощь. - person mattdlong; 10.12.2009

Вы пытались запустить EXPLAIN PLAN в хранимой процедуре? Я не вижу каких-либо непосредственных проблем ни с вашим кодом, ни с вашей хранимой процедурой, но полное сканирование таблицы серьезно сократит время выполнения вашего запроса. План объяснения сообщит вам, есть ли сканирование таблиц, а затем вы сможете настроить свой запрос, чтобы ускорить его.

person AJ.    schedule 08.12.2009

Это не проблема вашей программы odp.net. Причина в SELECT. Если таблица содержит много записей, возможно, оптимизатор решит запустить полное сканирование таблицы, в зависимости от ваших параметров. Ознакомьтесь с объясните план, как оператор работает. Если вы не видите ничего полезного. Попробуйте отследить оператор, чтобы см. физические чтения.

person Christian13467    schedule 09.12.2009