0

我有一个似乎很慢的存储过程。

在 Oracle SQL Developer 中执行;

SET TIMING ON;

DECLARE
  CUR_OUT UTILS.T_CURSOR;
  P_ARTTYID NUMBER;
  P_ORDERST VARCHAR2(200);
  P_DRUMNO VARCHAR2(200);
  P_SHIPPINGNO VARCHAR2(200);
  P_DELIVERYDATEFROM DATE;
BEGIN
  P_ARTTYID := 2;
  P_ORDERST := '3';
  P_DRUMNO := '611-480';
  P_SHIPPINGNO := NULL;
  P_DELIVERYDATEFROM := '2005-01-01';

  C_T_ORDER_GETOVERVIEW(
    CUR_OUT => CUR_OUT,
    P_ARTTYID => P_ARTTYID,
    P_ORDERST => P_ORDERST,
    P_DRUMNO => P_DRUMNO,
    P_SHIPPINGNO => P_SHIPPINGNO,
    P_DELIVERYDATEFROM => P_DELIVERYDATEFROM
  );

  --DBMS_OUTPUT.PUT_LINE('CUR_OUT = ' || CUR_OUT); -- Doesn´t work ;|
END;

给出“语句输出”

anonymous block completed
139ms elapsed

现在的问题是当我使用 Microsoft.Practices.EnterpriseLibrary.Data 从我的 VB.NET 应用程序中调用它时。返回 System.Data 的Database.ExecuteReader()IDataReader和以下函数将 IDataReader 转换为 DataSet。

    Public Shared Function ConvertIDataReaderToDataSet(ByVal reader As IDataReader) As DataSet
        Dim schemaTable As DataTable = reader.GetSchemaTable()
        Dim dataTable As DataTable = New DataTable

        For intCounter As Integer = 0 To schemaTable.Rows.Count - 1
            Dim dataRow As DataRow = schemaTable.Rows(intCounter)
            Dim columnName As String = CType(dataRow("ColumnName"), String)
            Dim column As DataColumn = New DataColumn(columnName, CType(dataRow("DataType"), Type))
            dataTable.Columns.Add(column)
        Next

        Dim dataSet As DataSet = New DataSet
        dataSet.Tables.Add(dataTable)

        'dataSet.Load(reader, LoadOption.OverwriteChanges, dataTable) ' DEBUG
        While reader.Read()
            Dim dataRow As DataRow = dataTable.NewRow()
            For intCounter As Integer = 0 To reader.FieldCount - 1
                dataRow(intCounter) = reader.GetValue(intCounter)
            Next
            dataTable.Rows.Add(dataRow)
        End While

        Return dataSet
    End Function

调试和单步执行函数在“While reader.Read()”行结束。还使用 DataSet.Load() 尝试了另一个版本,但结果相同。

在 MSDN上找到了这个线程,其他有相同问题的人似乎已经通过添加索引来调整他们的查询来解决它。

当程序似乎有效(在 ~100 - 200 毫秒内响应)并且 IDataReader.Read() 刚刚结束(或在后台继续?)时,我如何继续调查该问题?

  • 我可以用另一种(更好的)方式计时吗?
  • 是否可能涉及任何表或事务锁?

高度赞赏所有建议:)

4

1 回答 1

0

您在 SQL Developer 中的测试只是测量打开游标所需的时间。打开游标不会导致 Oracle 实际执行查询——直到您从游标中获取数据时才会发生这种情况,并且每次获取时,Oracle 将继续处理查询以获取下一组行。Oracle 通常不需要在任何时间点执行整个查询。作为一个可比较的测试,您的 PL/SQL 块需要从游标中获取所有数据。就像是

DECLARE
  CUR_OUT UTILS.T_CURSOR;
  P_ARTTYID NUMBER;
  P_ORDERST VARCHAR2(200);
  P_DRUMNO VARCHAR2(200);
  P_SHIPPINGNO VARCHAR2(200);
  P_DELIVERYDATEFROM DATE;
BEGIN
  P_ARTTYID := 2;
  P_ORDERST := '3';
  P_DRUMNO := '611-480';
  P_SHIPPINGNO := NULL;
  P_DELIVERYDATEFROM := '2005-01-01';

  C_T_ORDER_GETOVERVIEW(
    CUR_OUT => CUR_OUT,
    P_ARTTYID => P_ARTTYID,
    P_ORDERST => P_ORDERST,
    P_DRUMNO => P_DRUMNO,
    P_SHIPPINGNO => P_SHIPPINGNO,
    P_DELIVERYDATEFROM => P_DELIVERYDATEFROM
  );

  LOOP
    FETCH cur_out
     INTO <<list of variables to fetch data into>>;

    EXIT WHEN cur_out%notfound;
  END LOOP;

  --DBMS_OUTPUT.PUT_LINE('CUR_OUT = ' || CUR_OUT); -- Doesn´t work ;|
END;

您是说在您的 .Net 代码中,该reader.Read()行永远不会返回吗?或者你是说你的代码在那时中止?

于 2011-09-21T14:00:49.460 回答