注: 最初に DBA Exchange に投稿することを検討しましたが、これは .NET クライアントの問題であることを考えると、最初にここで質問するのが最善であると考えました。
Oracle 11g 開発サーバーに格納されている 2 つの関数があり、これらは ODP.NET を使用して呼び出されます (Oracle.DataAccess ではなく Oracle.ManagedDataAccess を使用)。
この 2 つの関数は、SQL Developer では非常に高速ですが (これは理にかなっており、約 20,000 レコードのみを選択する単純なクエリです)、パフォーマンス (System.Diagnostics.Stopwatch で測定) は、私の C# アプリから ODP を使用して実行した場合、それほど優れていませんでした。ネット。
結果は次のとおりです: (「変換時間と作成時間は無視してください。これらはクエリ プロセスの一部ではありません)
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
GET_TVM_ALL の 5 秒の実行時間は途方もなく長いです。さらに驚くべきことは、2 番目のクエリがはるかに高速であることです。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
ご覧のとおり、内容に関係なく、最初のクエリは常に遅いようです。これを証明するために、ばかげたダミー関数を作成しました。
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;
さて、私のコードからそれを呼び出して、見てみましょう:
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
これは、私が実行している最初のクエリが常に遅いことを証明しています。
追加情報:呼び出している関数ごとに新しい接続を開いたり閉じたりしています。
ちなみに私のヘルパー関数は次のとおりです。
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;
}
}