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

StackOverflow https://stackoverflow.com/questions/1869879

Вопрос

У нас возникли серьезные проблемы с производительностью запросов 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...
              }
       }
}

Любое руководство будет высоко оценено.

Это было полезно?

Решение

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

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

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top