简体   繁体   中英

How to improve stored procedure execution performance?

My task is to call a stored procedure from the Oracle database. The stored procedure is defined as follows:

CREATE OR REPLACE PROCEDURE my_st_proc
   (pname IN VARCHAR2, pdate IN date, o_rc OUT sys_refcursor, o_flag OUT number);

So it takes two input arguments and returns two output arguments, one of which is a cursor. When testing performance in pl\\sql developer with the following code, it completes within 2 - 3 seconds.

DECLARE   
   pname varchar2(300) := 'john doe';  
   pdate date := to_date('01/01/1900','dd/mm/yyyy');

   o_flag number;
   o_data sys_refcursor;

   --MyRec describes the fields, returned by the cursor
   TYPE MyRec IS RECORD 
        (cAccount VARCHAR2(20), cBalance number, cDate date, cCurr varchar2(8));
   rec MyRec;
BEGIN   
    my_st_proc(pname,pdate,o_data,o_flag); 
    dbms_output.put_line(o_flag);

    LOOP
        FETCH o_data INTO rec;
        EXIT WHEN o_data%NOTFOUND;
        dbms_output.put_line(
            rec.cAccount||','||rec.cBalance||','||rec.cDate||','||rec.cCurr);
    END LOOP;

    close o_data;
END;

However when I call the stored procedure via ODP.Net it takes up to two seconds more to complete (3 - 5 seconds).

const string p_name = "pname";
const string p_date = "pdate";
const string p_data = "o_data";
const string p_flag = "o_flag";

using (var connection = new OracleConnection("my connection"))
{
    var command = connection.CreateCommand();
    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = "my_st_proc";

    var pname = command.Parameters.Add(p_name, OracleDbType.Varchar2);
    pname.Direction = ParameterDirection.Input;
    var pdate = command.Parameters.Add(p_date, OracleDbType.Date);
    pdate.Direction = ParameterDirection.Input;

    command.Parameters.Add(p_data, OracleDbType.RefCursor).Direction = 
        ParameterDirection.Output;

    var pflag = command.Parameters.Add(p_flag, OracleDbType.Int32);
    pflag.Direction = ParameterDirection.Output;

    if (command.Connection.State != ConnectionState.Open)
        command.Connection.Open();

    command.Parameters[p_name].Value = name;
    command.Parameters[p_date].Value = date;

    DateTime bdate = DateTime.Now;
    command.ExecuteNonQuery();

    if (((OracleDecimal)command.Parameters[p_flag].Value).ToInt32() == 1)
    {

    }
    else
    {
        using (var oreader = command.ExecuteReader())
        {
            if (oreader != null)
            {
                try
                {
                    while (oreader.Read()){ }
                }
                finally
                {
                    oreader.Close();
                }
            }
        }
    }
    MessageBox.Show(DateTime.Now.Subtract(bdate).ToString());
}

The most time consuming lines of code appeared to be

command.ExecuteNonQuery();

and

command.ExecuteReader()

The number of lines returned by the cursor is not more than 10 - 15, few enough and reading them through the reader does take milliseconds; so I suppose it's not the FetchSize or RowSize issue.

Is there anything I can do to improve performance with ODP.Net in this cituation?

First, you function includes opening the database. I guess in your other tool, you already did the connection and just executed the command. Depending on your database security and location, that easily takes 1-10 seconds.

I don't think this will actually gain you seconds, but you never used CommandType.StoredProcedure . Instead you built SQL yourself. Let ODP.Net worry about that. Just pass the correct comand type and the procedures name as text.

Start by making sure the execution plans are actually the same.

Work with your DBAs and ask them to capture an explain plan for both the stand alone run (aqua data studio) and your odp.net call and confirm they are in fact the same. If they are not, then that will probably explain your problem. You can then try adding "enlist=false" to your connection string but better yet have the DBA's update the statistics on the related tables, hopefully fixing the slow plan. See https://stackoverflow.com/a/14712992/852208 for more info.

I have had this same issue and it came down to oracle being less optimistic about the execution plan when a distributed transaction could be involved.

The above answer is from: https://stackoverflow.com/a/15886630/852208 . This is essentially a "runs fine from X but not from Y" so it may be a duplicate but we'll see.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM