使用ODP.NET进行的第一次查询总是很慢

rom*_*the 8 c# sql oracle performance odp

注意:我考虑首先在DBA Exchange上发布这个,但考虑到这是一个.NET客户端问题,我认为最好先问这里.

我有两个存储在Oracle 11g开发服务器中的函数,这些函数使用ODP.NET调用(使用Oracle.ManagedDataAccess而不是Oracle.DataAccess).

这两个函数在SQL Developer中是闪电般快速的(有意义的是,它们只是简单的查询,只选择了大约20,000条记录),但是当使用ODP从我的C#应用​​程序中激发时,性能(使用System.Diagnostics.Stopwatch测量)并不是很好.净.

以下是结果:(忽略'转换时间和撰写时间,它们不是查询过程的一部分)

Connecting time - GET_TVM_ALL: 00:00:00.0553501
Query time - GET_TVM_ALL: 00:00:05.3467058
Conversion time: 00:00:07.6508273
Connecting time - GET_TVM_STATUS_ALL_FUNC: 00:00:00.0006773
Query time - GET_TVM_STATUS_ALL_FUNC: 00:00:00.0256008
Conversion time: 00:00:03.7280097
Composing time: 00:00:00.0157274
Total Elapsed: 00:00:16.7796351
Run Code Online (Sandbox Code Playgroud)

GET_TVM_ALL的执行时间为5秒,非常高.更令人惊讶的是,第二个查询要快得多.这很奇怪,因为毫无疑问,对于超过20倍的记录数量来说,这是一个更复杂的查询.

所以我换了它们,这就是结果:

Connecting time - GET_TVM_STATUS_ALL_FUNC: 00:00:00.0573807
Query time - GET_TVM_STATUS_ALL_FUNC: 00:00:05.2981962
Conversion time: 00:00:03.6474905
Connecting time - GET_TVM_ALL: 00:00:00.0007322
Query time - GET_TVM_ALL: 00:00:00.0070785
Conversion time: 00:00:07.2473809
Composing time: 00:00:00.0154049
Total Elapsed: 00:00:16.2268687
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,看起来第一个查询总是很慢,无论其内容如何.为了证明这一点,我做了一个愚蠢的虚拟函数:

CREATE OR REPLACE FUNCTION GET_DUMMY
RETURN SYS_REFCURSOR
AS
    -- REFCURSOR to return data
    pCursor SYS_REFCURSOR;
    BEGIN
        OPEN pCursor FOR SELECT 1 FROM DUAL;      
        RETURN pCursor;
    END;
Run Code Online (Sandbox Code Playgroud)

现在,从我的代码中调用它,让我们来看看:

Connecting time - GET_DUMMY: 00:00:00.0581149
Query time - GET_DUMMY: 00:00:05.4103165
Conversion time: 00:00:00.0005617
Connecting time - GET_TVM_STATUS_ALL_FUNC: 00:00:00.0006580
Query time - GET_TVM_STATUS_ALL_FUNC: 00:00:00.0759243
Conversion time: 00:00:03.7577602
Connecting time - GET_TVM_ALL: 00:00:00.0000489
Query time - GET_TVM_ALL: 00:00:00.0037654
Conversion time: 00:00:07.5071360
Composing time: 00:00:00.0152159
Total Elapsed: 00:00:16.7819147
Run Code Online (Sandbox Code Playgroud)

所以这证明了,我正在运行的第一个查询总是很慢.

额外信息:我正在打开和关闭我正在呼叫的每个功能的新连接.

顺便说一句,这是我的助手功能:

public static List<T> ExecuteFunction<T>(string strConnection, string strFunction, OracleDbType returnType, List<DataOracleParameter> parameterList) where T : new()
{
    Stopwatch watch = new Stopwatch();

    using (OracleConnection objConnection = new OracleConnection(strConnection))
    {

        // Create the command object and set attributes
        OracleCommand objCommand = new OracleCommand(strFunction, objConnection);
        objCommand.CommandType = CommandType.StoredProcedure;

        // Set the return parameter and type
        OracleParameter returnValue = new OracleParameter();
        returnValue.OracleDbType = returnType;
        returnValue.Direction = ParameterDirection.ReturnValue;
        objCommand.Parameters.Add(returnValue);

        // Set additional parameters
        if (parameterList != null && parameterList.Count > 0)
        {
            foreach (DataOracleParameter parameter in parameterList)
            {
                OracleParameter inputValue = new OracleParameter();
                inputValue.ParameterName = parameter.ParameterName;
                inputValue.OracleDbType = parameter.ParameterType;
                inputValue.Value = parameter.ParameterValue;
                inputValue.Direction = ParameterDirection.Input;
                objCommand.Parameters.Add(inputValue);
            }
        }

        // Create a data adapter to use with the data set
        OracleDataAdapter dataAdapter = new OracleDataAdapter(objCommand);

        // Create and fill the dataset
        DataSet dataSet = new DataSet();

        watch.Start();
        dataAdapter.Fill(dataSet);
        watch.Stop();
        Console.WriteLine("Query time - {0}: {1}", strFunction, watch.Elapsed);

        List<T> valueList = dataSet.Tables[0].ToList<T>();

        return valueList;
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*ssi 2

首先,我建议您调整OracleCommand 对象上的FetchSize 。