Хранимая процедура Oracle медленно возвращает курсор на C #, быстро на TOAD

Мы используем asp.net mvc в качестве веб-приложения и oracle 12C в качестве базы данных, Oracle.DataAccess.Client (12.1.0, 64-разрядная версия) для подключения к базе данных Oracle, а наше приложение asp.net MVC работает на 64-разрядной машине. также.

Одна из наших хранимых процедур возвращает курсор как выходной параметр.

Теперь та же хранимая процедура занимает чуть меньше секунды, когда мы выполняем ее в TOAD или SQL Developer, но когда C # выполняет ту же хранимую процедуру, это занимает около 35 секунд .. !!! вернуться обратно. TOAD, SQL Developer и сервер asp.net iis находятся на моем локальном компьютере, а сервер Oracle находится на другом компьютере.

В C # я регистрировал все виды таймингов, например, сколько времени потребовалось для открытия соединения, с какой отметкой времени C # вызывает хранимую процедуру и в какое время она завершилась и вернулась, сколько времени потребовалось для преобразования DataSet в C # List. после наблюдения за временем мы видим, что следующий оператор занимает 35 секунд

            OracleDataAdapter loDataAdapter = new  OracleDataAdapter(loCommand);
            LogInfo("fill DataTable");//logs time stamp saying start
            loDataAdapter.Fill(loDataTable);
            LogInfo("fill DataTable",false);//logs time stamp saying Done
            loDataAdapter = null;

Мы думали, что это может быть проблема с сетью, если это так, разработчик жабы и sql также должен занять одинаковое время, поэтому сеть не является проблемой.

Что мы пробовали: единственный подозреваемый, который у меня есть, это драйвер ODP.NET, поэтому удалил все клиенты Oracle и переустановил их, бесполезно.

Теперь пытаетесь узнать, есть ли что-то, что мне нужно настроить для подключения к файлу sqlnet.ora или tns? но не нашел ...

Вот полный код

общедоступная таблица данных GetDataTable (строка psStoredProcedure) {LogInfo (psStoredProcedure);

        //******************************************************************
        //Function.........GetDataTable
        //Description......Gets a data set (with the schema) from stored procedure
        //Input Param......(1)Stored procedure name
        //                 (2)Boolean to determine if we want to get the schema
        //Output...........Return DataTable 
        //
        //******************************************************************

        OracleCommand loCommand = new OracleCommand();
        OracleConnection loConnection = new OracleConnection(msConnectionString);
        DataTable loDataTable = new DataTable();

        //---Main Execution Block
        try
        {
            if (!(loConnection.State == ConnectionState.Open))
            {
                LogInfo("Open Conn");
                loConnection.Open();
                LogInfo("Open Conn",false);
            }

            //---Define the SelectCommand 
            if (moCommand == null)
            {
                loCommand = new OracleCommand();
            }
            else
            {
                loCommand = moCommand;
                moCommand = null;
            }

            loCommand.CommandText = psStoredProcedure;
            loCommand.Connection = loConnection;
            loCommand.CommandType = CommandType.StoredProcedure;

            //---Populate the dataset
            OracleDataAdapter loDataAdapter = new OracleDataAdapter(loCommand);
            LogInfo("fill DataTable");
            loDataAdapter.Fill(loDataTable);
            LogInfo("fill DataTable",false);
            loDataAdapter = null;
        }
        catch (Exception oExcep)
        {
            throw oExcep;
        }
        finally
        {
            //---Close the connection
            if (loConnection.State == ConnectionState.Open)
            {
                LogInfo("Close");
                loConnection.Close();
                LogInfo("Close", false);
            }

            loCommand = null;
            loConnection = null;
        }
        LogInfo(psStoredProcedure, false);
        return loDataTable;}

Ниже приведена хранимая процедура PL / SQL In:

CREATE OR REPLACE PROCEDURE REF_LIST_INQ ( 
ivID          IN VARCHAR2 DEFAULT NULL,        
ivAID         IN VARCHAR2 DEFAULT NULL,
ivDID           IN VARCHAR2 DEFAULT NULL, 
ivSelection        IN VARCHAR2 DEFAULT NULL, 
ivStartDate        IN VARCHAR2 DEFAULT NULL,
ivEndDate          IN VARCHAR2 DEFAULT NULL,       
ocRefList     OUT ES_PACKAGE.cursorType,
ovReturnCode       OUT VARCHAR2,
ovErrorMsg         OUT VARCHAR2  
)
AS

cmdSQL       VARCHAR2(4000) := NULL;
whereCause   VARCHAR2(2000) := NULL;
selectCause  VARCHAR2(2000) := NULL;


BEGIN
    /************
 --Hundreds of lines of PL/SQL Code for
    -- dynamically creating sql statements 
    -- and assigning it to 'selectCause' and 'whereCause'
*************************/

    cmdSQL :=  selectCause || whereCause || ' ORDER BY SD.MODIFIED_DATE DESC, SD.REFERRAL_NUMBER';

    OPEN ocRefList FOR cmdSQL;
    ovReturnCode := '0';

    EXCEPTION WHEN OTHERS THEN
         ovErrorMsg := 'REF_LIST_INQ - ' || SUBSTR(SQLERRM,1,200);
         ovReturnCode := '-1';

END REF_LIST_INQ;
/

person venu    schedule 16.02.2017    source источник
comment
Опубликуйте также свой тестовый код plsql - я предполагаю, что вы только возвращаете курсор, но не извлекаете из него все записи - что и делает оператор Fill.   -  person b_levitt    schedule 21.02.2017
comment
pl / sql внутри хранимой процедуры - это динамически созданный оператор, который назначается переменной cmdSQL. И в конце мы открываем курсор для этого оператора.   -  person venu    schedule 21.02.2017
comment
Как показано ниже, ОТКРЫТЬ ocReferralList ДЛЯ cmdSQL; Я скоро добавлю pl / sql в свой вопрос.   -  person venu    schedule 21.02.2017
comment
@b_levitt Обновлено   -  person venu    schedule 21.02.2017


Ответы (1)


Для меня это ответ, может быть, если кто-то сталкивается с такой же ситуацией, может попробовать.

После нескольких дней исследования мне помог следующий оператор C #.

loCommand.FetchSize = loCommand.FetchSize * 18192;

В соответствии с моим пониманием (я не умею описывать, стараюсь изо всех сил) это работает только для 64-битной версии, и если мы не укажем FetchSize, он будет продолжать извлекать предопределенный размер (я считаю, 128k) данных из открытого курсора в Oracle DB он будет выполнять циклические обходы до тех пор, пока не будут обработаны данные, предоставленные курсором.

Итак, вот полный код C #, но этот однострочный код имел большое значение.

    //******************************************************************
    //Function.........GetDataTable
    //Description......Gets a data set (with the schema) from stored procedure
    //Input Param......(1)Stored procedure name
    //                 (2)Boolean to determine if we want to get the schema
    //Output...........Return DataTable 
    //
    //******************************************************************

    OracleCommand loCommand = new OracleCommand();
    OracleConnection loConnection = new OracleConnection(msConnectionString);
    DataTable loDataTable = new DataTable();

    //---Main Execution Block
    try
    {
        if (!(loConnection.State == ConnectionState.Open))
        {
            LogInfo("Open Conn");
            loConnection.Open();
            LogInfo("Open Conn",false);
        }

        //---Define the SelectCommand 
        if (moCommand == null)
        {
            loCommand = new OracleCommand();
        }
        else
        {
            loCommand = moCommand;
            moCommand = null;
        }

        loCommand.CommandText = psStoredProcedure;
        loCommand.Connection = loConnection;
        loCommand.CommandType = CommandType.StoredProcedure;
//Here is the Hero
loCommand.FetchSize = loCommand.FetchSize * 18192;

        //---Populate the dataset
        OracleDataAdapter loDataAdapter = new OracleDataAdapter(loCommand);
        LogInfo("fill DataTable");
        loDataAdapter.Fill(loDataTable);
        LogInfo("fill DataTable",false);
        loDataAdapter = null;
    }
    catch (Exception oExcep)
    {
        throw oExcep;
    }
    finally
    {
        //---Close the connection
        if (loConnection.State == ConnectionState.Open)
        {
            LogInfo("Close");
            loConnection.Close();
            LogInfo("Close", false);
        }

        loCommand = null;
        loConnection = null;
    }
    LogInfo(psStoredProcedure, false);
    return loDataTable;}
person venu    schedule 02.03.2017